Python 在Django中,是否可以基于另一个数据库定义动态计算的设置?
(也许这个问题更多的是关于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的最佳实践》一书中所建议的那样,有许多设置文件非常流行,每个环境(例如生产、开发、测试、
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的设置对象在初始化设置对象时使用一次
(注意,当您从Django.conf import settings导入getattr(settings\u module,setting)
,返回时,实际上是导入一个对象,而不是一个模块)。结果将设置为设置对象上的属性<调用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…
)已经执行了,不会再执行了。这是一个好主意,尽管它确实是实现我想要的东西的一种黑客方式。我从来没有想过要这样处理这个问题。恭喜