flask特性之配置系统
我们在使用flask的时候,可以通过app.config来去取或者更新flask的配置,此外,flask的作者还针对配置的加载在Config类中提供多种方法,例如:from_envvar、from_pyfile、from_object等多种形式,那么其背后到底是如何实现的呢?今天我们就来看看flask的配置的神秘面纱。
源码奉上:
from .config import Config
from .config import ConfigAttribute
class Flask(_PackageBoundObject):
config_class = Config
# 以下的配置可由Flask的实例对象直接访问与修改,此处的精妙之处就是通过ConfigAttribute描述符类实现的
testing = ConfigAttribute("TESTING")
secret_key = ConfigAttribute("SECRET_KEY")
session_cookie_name = ConfigAttribute("SESSION_COOKIE_NAME")
permanent_session_lifetime = ConfigAttribute(
"PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta
)
send_file_max_age_default = ConfigAttribute(
"SEND_FILE_MAX_AGE_DEFAULT", get_converter=_make_timedelta
)
use_x_sendfile = ConfigAttribute("USE_X_SENDFILE")
default_config = ImmutableDict(
{
"ENV": None,
"DEBUG": None,
"TESTING": False,
"PROPAGATE_EXCEPTIONS": None,
"PRESERVE_CONTEXT_ON_EXCEPTION": None,
"SECRET_KEY": None,
"PERMANENT_SESSION_LIFETIME": timedelta(days=31),
"USE_X_SENDFILE": False,
"SERVER_NAME": None,
"APPLICATION_ROOT": "/",
"SESSION_COOKIE_NAME": "session",
"SESSION_COOKIE_DOMAIN": None,
"SESSION_COOKIE_PATH": None,
"SESSION_COOKIE_HTTPONLY": True,
"SESSION_COOKIE_SECURE": False,
"SESSION_COOKIE_SAMESITE": None,
"SESSION_REFRESH_EACH_REQUEST": True,
"MAX_CONTENT_LENGTH": None,
"SEND_FILE_MAX_AGE_DEFAULT": timedelta(hours=12),
"TRAP_BAD_REQUEST_ERRORS": None,
"TRAP_HTTP_EXCEPTIONS": False,
"EXPLAIN_TEMPLATE_LOADING": False,
"PREFERRED_URL_SCHEME": "http",
"JSON_AS_ASCII": True,
"JSON_SORT_KEYS": True,
"JSONIFY_PRETTYPRINT_REGULAR": False,
"JSONIFY_MIMETYPE": "application/json",
"TEMPLATES_AUTO_RELOAD": None,
"MAX_COOKIE_SIZE": 4093,
}
)
def __init__(
self,
import_name,
static_url_path=None,
static_folder="static",
static_host=None,
host_matching=False,
subdomain_matching=False,
template_folder="templates",
instance_path=None,
instance_relative_config=False,
root_path=None,
):
# 省略其他逻辑 保留配置相关的代码
# 初始化配置cofnig
self.config = self.make_config(instance_relative_config)
def make_config(self, instance_relative=False):
root_path = self.root_path
if instance_relative:
root_path = self.instance_path
defaults = dict(self.default_config)
defaults["ENV"] = get_env()
defaults["DEBUG"] = get_debug_flag()
return self.config_class(root_path, defaults)由代码可知,Flask类在初始化时就进行配置的初始化,即self.config = self.make_config(instance_relative_config),此处调用make_config方法,返回self.config_class所对应的类Config的实例化对象,在Config的实例化的时候,将默认配置self.default_config一起加载,并最终将生产的Config实例化对象赋予self.config,到此flask的配置的加载逻辑就结束,在开发时,直接可以操作app.config来进行读取和修改。
在代码中可以看到,flask通过描述符类ConfigAttribute将某些配置直接绑定在Flask类上,这样我们就可以直接修改Flask类实例对象的属性来达到修改配置的目的,比如app.testting=True,此处值得我们来学习,描述符类虽然比较抽象,但威力很大,后续将专门说说python的描述符类。
接下来看一下Config类的实现:
从Config的源码中可以看到, Config类本质上是dict的子类,所以dict的原生的各种方法,Config同样支持。另外Config类中定义了多种加载配置的方法,包括from_envvar、from_pyfile、from_object、from_json、from_mapping、get_namespace。 from_开头的方法实现起来简单,我们可以根据自己的需求来选择使用何种加载配置的方法。在此,我们说说get_namespace方法,由实现可知,改方法是匹配所有以参数namespace开头的配置项,让我们看一个例子:
通过get_namespace方法,可以方便的寻找同一类配置。
配置的相关操作: 修改:
app.config["example"] = "example"
app.testting = False 这种方式默认只提供有限的配置项
app.config.update(TESTING=True)
删除:
del app.config["example"]
参考文档:
Last updated
Was this helpful?