Flask:如何管理不同环境的数据库?
我正在开发一个应用程序,外观类似于
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 个回答
你可以创建一个叫做“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/。
我想这就是你要找的内容:
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类,方法可以是通过环境变量或者其他你选择的方式。
我使用的解决方案:
#__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"