(也许这个问题更多的是关于Python,但Django是上下文,所以在这里)
假设您需要一个设置FOO
,其值取决于设置BAR
的值(最简单的情况是使CELERY_RESULT_BACKEND
等于BROKER_URL
)。
如果您只有一个设置文件,那么很容易实现:
BAR = some_value
FOO = some_function(BAR)
然而,拥有许多设置文件非常受欢迎,每个环境都有一个(例如制作,开发,测试,舞台等),正如书中的project layout所提出的那样,“Django的两个Scoops: Django 1.5“的最佳实践。
在这种情况下,有一个settings.base
模块,其中包含settings.dev
,settings.prod
等所有内容,它们会添加自己的特定值或覆盖settings.base
中定义的值。 {1}}。
当我想在某些模块中覆盖BAR
时会出现问题,但我必须记得每次重写后重新计算FOO
。这很容易出错,而不是干。
lambda函数不起作用,因为该设置是可调用的,而不是结果值。内置函数/装饰器property
将是理想的,但它只能在类(新式)中使用。我什么都不知道。
想法?
答案 0 :(得分:0)
是的,设置文件也只是一个python脚本。
大多数人都已经建立了模板路径设置。
现在让我们想象一下:
ref = {
'dev': 'FOO',
'qa': 'BAR'
'prod': 'BAZ'
}
ENV = 'PROD' # Can also be DEV or QA
DYNAMIC_SETTING = ref.get(ENV.lower(), None) # => 'BAZ'
答案 1 :(得分:0)
稍微讨厌:
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')
这个想法如下:
getattr(settings_module, setting)
一次(请注意,当您执行from django.conf import settings
实际导入对象而不是模块时)。结果设置为设置对象的属性。调用__get__
,返回self
,因此settings.FOO
是DynamicWrapper
实例。 settings.FOO
时,这将在__get__
对象上再次调用DynamicWrapper
,这是您希望它返回实际值的时间。该值根据some_func
计算,并返回值而不是DynamicWrapper
对象。settings.FOO
的值也会调用__get__
方法,但这次计算出的值缓存为self._computed_val
并立即返回。 如果有多个Settings
个对象,当FOO
以不同于django.conf.settings
的方式访问BAR
或{{1}}时,这不会处理(边缘)情况没有定义的。