Flask:如何管理不同环境的数据库?

11 投票
5 回答
20608 浏览
提问于 2025-04-17 20:10

我正在开发一个应用程序,外观类似于

facebook/
         __init__.py
         feed/
             __init__.py
             business.py
             views.py
             models/
                    persistence.py
                    user.py
         chat/
             __init__.py
             models.py
             business.py
             views.py
         config/
                dev.py
                test.py
                prod.py 

我想要有三个环境:开发(Dev)测试(Test)生产(Production)
我有以下要求:
a.) 当我启动服务器时,使用命令python runserver.py,我希望能指定想要连接的环境——开发测试生产
b.) 开发生产环境应该已经建立好数据库结构,只需要连接到机器上。
c.) 我希望我的测试环境能连接到sqlite数据库,并创建数据库结构,运行测试。

我想知道如何通过配置的方式来实现这些,这样就不需要在代码中硬编码任何与数据库相关的内容。

在flask中有没有好的设计模式可以使用?

目前我的runserver.py中硬编码了环境,这让我不太满意,

app = Flask(__name__)
app.config['SECRET_KEY'] = dev.SECRET_KEY

我在寻找比我现在的想法更好的解决方案。

5 个回答

4

你可以创建一个叫做“config”的模块,这个模块里存放着每个环境的配置。之后,你可以通过设置一个shell变量来指定当前正在运行的环境。

如果你在主init文件中初始化你的flask应用,那么配置也可以在这里设置。这就是我设置配置的方法:

def setup_config(app):
    """Set the appropriate config based on the environment settings"""
    settings_map = {'development': DevelopmentSettings,
                    'staging': StagingSettings,
                    'testing': TestingSettings,
                    'production': ProductionSettings}
    env = environ['ENV'].lower()
    settings = settings_map[env]
    app.config.from_object(settings)

在运行开发服务器或者测试之前设置环境变量可能会很麻烦,所以我用一个makefile来自动化这些操作。

另外,看看flask-script的文档 http://flask-script.readthedocs.org/en/latest/

6

我想这就是你要找的内容:

http://flask.pocoo.org/docs/config/#configuring-from-files

另外,你也可以看看flask-empty这个项目,它是一个为flask应用准备的模板,里面有针对不同环境的配置。

https://github.com/italomaia/flask-empty

你可以在config.py文件中这样指定你的配置:

class Dev(Config):
    DEBUG = True
    MAIL_DEBUG = True
    SQLALCHEMY_ECHO = True
    SQLALCHEMY_DATABASE_URI = "sqlite:////tmp/%s_dev.sqlite" % project_name

这里是继承了Config类,Config类可以包含你的默认设置。接着,main.py文件有一些方法可以根据config.py文件创建flask实例,而manage.py则决定加载哪个配置。

这里有一段来自main.py的代码,让你了解一下:

def app_factory(config, app_name=None, blueprints=None):
    app_name = app_name or __name__
    app = Flask(app_name)

    config = config_str_to_obj(config)
    configure_app(app, config)
    configure_blueprints(app, blueprints or config.BLUEPRINTS)
    configure_error_handlers(app)
    configure_database(app)
    configure_views(app)

    return app

然后,manage.py会根据你在命令行输入的参数来设置环境,不过你可以大致了解它是怎么工作的(注意这需要flask-script):

from flask.ext import script

import commands

if __name__ == "__main__":
    from main import app_factory
    import config

    manager = script.Manager(app_factory)
    manager.add_option("-c", "--config", dest="config", required=False, default=config.Dev)
    manager.add_command("test", commands.Test())
    manager.run() 

从这里你可以选择所需的Config类,方法可以是通过环境变量或者其他你选择的方式。

24

我使用的解决方案:

#__init__.py
app = Flask(__name__)
app.config.from_object('settings')
app.config.from_envvar('MYCOOLAPP_CONFIG',silent=True)

在应用程序加载的同一层级:

#settings.py
SERVER_NAME="dev.app.com"
DEBUG=True
SECRET_KEY='xxxxxxxxxx'


#settings_production.py
SERVER_NAME="app.com"
DEBUG=False

那么,如果环境变量 MYCOOLAPP_CONFIG 不存在,只有 settings.py 会被加载,这个文件会引用默认设置(对我来说是开发服务器)。
这就是为什么设置 "silent=True",第二个配置文件就不需要了,因为 settings.py 是开发的默认设置,并且包含了一些常用配置的默认值。

如果加载了其他的设置文件,那么这些文件里的值会覆盖原始文件中的值。(在我的例子中,DEBUG 和 SERVER_NAME 会被覆盖,而 SECRET_KEY 在所有服务器上保持不变)

你唯一需要自己搞清楚的就是你启动应用程序的方式。
在启动之前,环境变量 MYCOOLAPP_CONFIG 应该被设置好。
例如,我使用 supervisor 守护进程在生产服务器上运行,我只需在 supervisor 配置文件中加入这个:

environment=MYCOOLAPP_CONFIG="/home/tigra/mycoolapp/settings_production.py"

通过这种方式,你可以轻松管理所有的配置文件,而且还可以将这些文件排除在 git 或其他版本控制工具之外。

在 Linux 中,默认的方式是在启动之前在控制台输入:
export MYCOOLAPP_CONFIG="/home/tigra/mycoolapp/settings_production.py"

撰写回答