Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在Django中,是否可以基于另一个数据库定义动态计算的设置?_Python_Django_Settings - Fatal编程技术网

Python 在Django中,是否可以基于另一个数据库定义动态计算的设置?

Python 在Django中,是否可以基于另一个数据库定义动态计算的设置?,python,django,settings,Python,Django,Settings,(也许这个问题更多的是关于Python的,但Django是上下文,所以就这样) 假设您需要一个设置FOO,其值取决于设置BAR的值(最简单的情况是使cellery\u RESULT\u BACKEND等于BROKER\u URL) 如果只有一个设置文件,则很容易实现: BAR = some_value FOO = some_function(BAR) 然而,正如《Django的两个勺子:Django 1.5的最佳实践》一书中所建议的那样,有许多设置文件非常流行,每个环境(例如生产、开发、测试、

(也许这个问题更多的是关于Python的,但Django是上下文,所以就这样)

假设您需要一个设置
FOO
,其值取决于设置
BAR
的值(最简单的情况是使
cellery\u RESULT\u BACKEND
等于
BROKER\u URL

如果只有一个设置文件,则很容易实现:

BAR = some_value
FOO = some_function(BAR)
然而,正如《Django的两个勺子:Django 1.5的最佳实践》一书中所建议的那样,有许多设置文件非常流行,每个环境(例如生产、开发、测试、阶段等)有一个

在这种情况下,有一个
settings.base
模块,它与所有内容一起由
settings.dev
settings.prod
等导入,这些模块添加自己的特定值或覆盖
settings.base
中定义的值

当我想覆盖其中一些模块中的
BAR
时,就会出现问题,但我必须记住每次覆盖之后都要重新计算
FOO
。这很容易出错,而且不干燥

lambda函数不起作用,因为该设置是可调用的,而不是结果值。内置函数/装饰器是理想的,但它只能在类中使用(新样式)。我不知道还有其他类似的事情


想法?

是的,设置文件也是一个python脚本

大多数人已经这样做来构建模板路径设置

现在让我们想象一下:

ref = {
    'dev':  'FOO',
    'qa':   'BAR'
    'prod': 'BAZ'
}

ENV = 'PROD'  # Can also be DEV or QA

DYNAMIC_SETTING = ref.get(ENV.lower(), None)  # => 'BAZ'
有点粗俗:

class DynamicWrapper(object):
    _initialized = False

    def __init__(self, wrapped_name)
        self._wrapped = wrapped_name

    def __get__(self):
        if not self._initialized:
            self._initialized = True
            return self
        if not hasattr(self, '_computed_val'):
            from django.conf import settings
            val = getattr(settings, self._wrapped)
            self._computed_val = some_func(val)
        return self._computed_val

BAR = 'some_value'
FOO = DynamicWrapper('BAR')
其思路如下:

  • Django的设置对象在初始化设置对象时使用一次
    getattr(settings\u module,setting)
    (注意,当您从Django.conf import settings导入
    时,实际上是导入一个对象,而不是一个模块)。结果将设置为设置对象上的属性<调用code>\uu get\uu
    ,返回
    self
    ,因此
    settings.FOO
    DynamicWrapper
    实例
  • 当访问
    settings.FOO
    时,这将在
    DynamicWrapper
    对象上第二次调用
    \uuuu get\uuu
    ,此时您希望它返回实际值。根据
    some_func
    计算该值,并返回该值,而不是
    DynamicWrapper
    对象
  • 任何后续尝试获取
    settings.FOO
    的值时,也会调用
    \uuu get\uuu
    方法,但这一次计算出的值会缓存为
    self.\u computed\u val
    ,并立即返回

当存在多个
Settings
对象时,当通过
django.conf.Settings
以外的其他方式访问
FOO
时,或者当未定义
BAR
时,这不处理(边缘)情况

嗯。这有点不整洁,但可能会将依赖设置拆分成不同的文件,并在设置栏后导入?我想你误解了我的需要。您发布的
DYNAMIC\u SETTING
并非如此:如果我在您的代码片段之后更改
ENV
,然后再次访问
DYNAMIC\u SETTING
,则其值不会更改。为什么?因为那行(
DYNAMIC\u SETTING=ref…
)已经执行了,不会再执行了。这是一个好主意,尽管它确实是实现我想要的东西的一种黑客方式。我从来没有想过要这样处理这个问题。恭喜