将Flask配置作为属性而不是dict键访问

时间:2019-10-16 15:43:33

标签: python flask

在Flask中处理应用程序配置时,通常建议使用config对象上可用的flask.Flask字典,例如flask.current_app.config["TESTING"]

对此进行填充的一个建议是使用类和继承为每个环境分隔配置:

class Config:
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite:///:memory:'

class ProductionConfig(Config):
    DATABASE_URI = 'mysql://user@localhost/foo'

class DevelopmentConfig(Config):
    DEBUG = True

# Example usage:
app = flask.Flask(__name__)
app.config.from_object(ProductionConfig)

db_uri = app.config["DATABASE_URI"]

这样做的缺点是,尽管已经使用类属性定义了键,但是我们还是使用字符串键来访问它们,而这些键最终会在代码周围被引用。如果我键入错误的键,则不会在我的IDE中收到警告,并且会在运行时得到KeyError。我也没有得到配置中对象的类型推断。

能够以类似方式填充Flask配置很好,但是可以更好地访问这些值,就像我可以访问对象上的普通属性一样。

我已经想到了一些方法,但是似乎都没有一个理想的方法:

  1. 将每个配置键包装在函数中,例如get_database_uri()-只要这是访问配置的唯一方法,就知道可用的键及其值的类型。需要为每个新的配置键编写一个函数。
  2. 在Flask配置中存储单个Config对象,例如app.config["config"] = ProductionConfig()。使用类型提示或包装函数,我们可以输入内容,但是将配置对象存储在配置中很奇怪,并且我们无法自动设置Flack特定值,例如TESTING
  3. 忘记使用app.config,并使用其他任何解决方案。

有没有人发现还可以与Flask的配置集成的更清洁的解决方案?

1 个答案:

答案 0 :(得分:3)

可以通过覆盖app.config来配置用于Flask.config_class的类。编写flask.config.Config的子类,该子类定义__getattr__来查找密钥,并将其分配给config_class属性。

from flask.app import Flask
from flask.config import Config

class AttrConfig(Config):
    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(key)

    def __dir__(self):
        out = set(self.keys())
        out.update(super().__dir__())
        return sorted(out)

class CustomFlask(Flask):
    config_class = AttrConfig

app = CustomFlask(__name__)

但是,鉴于它们是动态加载的,因此没有可靠的方法可以使IDE理解这些属性。实现__dir__将使它们显示在Python或IPython Shell的制表符补全中,但是IDE通常不执行模块代码以提供自省功能,因此这不会影响它们。