Flask中优雅使用config
2017-07-31 本文已影响1548人
jiaxiaolei
flask原生提供current_app, application 一旦启动,就可以通过current_app.config 获取当前application的所有配置。
公司有一个使用flask做web framework的项目,其中的使用方式如下:
# filename: config.py
APP_ENV = "testing"
class BaseConfig:
DEBUG = False
class DevelopmentConfig(BaseConfig):
CRP_URL = 'xxxx'
...
class TestingConfig(BaseConfig):
CRP_URL = 'xxxx'
...
configs = {
'development': DevelopmentConfig,
'testing': TestingConfig,
}
项目中的应用举例1:
# filename: uop/pool/handler.py
from config import APP_ENV, configs
...
pool_api = Api(pool_blueprint, errors=pool_errors)
CRP_URL = configs[APP_ENV].CRP_URL
class PoolListAPI(Resource):
pass
项目中的应用举例2:
# filename: crp/res_set/handler.py
from config import TestingConfig, DevelopmentConfig
nginx_ip = DevelopmentConfig.nginx_ip
MONGODB_SCRIPT_PATH = DevelopmentConfig.MONGODB_SCRIPT_PATH
改进策略:
flask中提供current_app来标示当前application。相关的config信息在调用create_app()的时候已经对application进行了初始化,在业务代码中不应该再次使用从配置文件中去加载,也不应该和不需要关心当前的配置环境(dev,test,prod) 。而是直接使用已经初始化的create_app.
改写如下:
from flask import current_app
CRP_URL = current_app.config['CRP_URL']
nginx_ip = current_app.config['nginx_ip']
MONGODB_SCRIPT_PATH = current_app.config['MONGODB_SCRIPT_PATH']
如果改用current_app, 相关变量都可以使用了,都没有必要提前去获取了。
扩展阅读:
flask 源码中的一个例子:
https://github.com/pallets/flask/blob/master/flask/json/init.py
def _dump_arg_defaults(kwargs):
"""Inject default arguments for dump functions."""
if current_app:
bp = current_app.blueprints.get(request.blueprint) if request else None
kwargs.setdefault(
'cls',
bp.json_encoder if bp and bp.json_encoder
else current_app.json_encoder
)
if not current_app.config['JSON_AS_ASCII']:
kwargs.setdefault('ensure_ascii', False)
kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS'])
else:
kwargs.setdefault('sort_keys', True)
kwargs.setdefault('cls', JSONEncoder)
flask example 中的一个例子:
https://github.com/pallets/flask/blob/master/examples/flaskr/flaskr/blueprints/flaskr.py
from sqlite3 import dbapi2 as sqlite3
from flask import Blueprint, request, session, g, redirect, url_for, abort, \
render_template, flash, current_app
# create our blueprint :)
bp = Blueprint('flaskr', __name__)
def connect_db():
"""Connects to the specific database."""
rv = sqlite3.connect(current_app.config['DATABASE'])
rv.row_factory = sqlite3.Row
return rv
def init_db():
"""Initializes the database."""
db = get_db()
with current_app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()