在Django中覆盖全局设置的最佳方法

时间:2009-03-25 14:36:02

标签: django

我有一个包含多个应用程序(例如两个)的Django项目,并且都需要不同版本的 MEDIA_ROOT MEDIA_URL

文档确实指定了如何修改特定设置,但这就是我所做的。

我创建了一个project1 / settings.py,

# project1/settings.py, 
from django.conf import settings

settings.MEDIA_URL = 'foo'
settings.MEDIA_ROOT = 'bar'

然后我将该应用程序的init模块修改为加载模块:

# project1/__init__.py
import settings

有效!专门的设置文件有选择地愉快地覆盖全局设置文件。我喜欢这个是项目设置文件在逻辑位置。

我的问题是 - 这种做法是否有任何警告,实现这一目标的最佳做法是什么?

2 个答案:

答案 0 :(得分:4)

Jarret是对的。最佳情况:如果在重新启动服务器后运行非常简单的测试,这将有效。几乎任何其他东西都会破坏它。

如果您只是使用MEDIA_ *作为常量,我建议使用其他常量。如果您确实将它们用于文件字段的默认上载设置,则听起来您的项目将要求您指定路径。这不应该太难。

您需要克服的两个问题是您当前的方案无法解决的问题:

  1. 每次发出请求时动态设置变量
  2. 避免恶劣的竞争条件
  3. 1最好通过自定义MiddleWare完成,可能使用process_request方法。

    是你想要避免的
    settings.MEDIA_URL = 'foo'
    

    全球变量滥用。这将带来问题2.由于process_request允许您传递HttpRequest对象,我建议将变量信息放在那里:

    class MyMiddleWare:
        def process_request(self,request):
            media_root = #some logic to parse request.path
            request.media_root = media_root
    

    您的静态链接必须引用request.media_root。

答案 1 :(得分:2)

我对这应该如何工作感到有点困惑。您将如何使用每个应用程序代码中的设置?

# project1/view.py
import settings
print settings.MEDIA_URL

# project1/view.py
from django.conf import settings
print settings.MEDIA_URL

在第一种情况下,由于您导入的设置是project1.settings,它本身没有MEDIA_URL属性,因此可能无效。

在第二种情况下,你最终不会遇到竞争条件吗?无论最后加载哪个应用程序,都会覆盖全局settings对象中的属性。这可能适用于您刚刚在本地运行并启动服务器,然后立即转到一个或另一个应用程序中的视图的情况,但是在像Apache这样的长时间运行的服务器中,它会使多个子进程保持引导并运行, - 从请求到请求使用它们,您的设置中的值将是不可预测的。请记住, init 中的代码只有在第一次导入时才会被处理...后续导入不会导致代码重新运行。

也许我在你的描述中遗漏了一些东西。

如果您有特定于应用程序的设置,则需要拥有自己的应用程序特定设置,并根据需要对逻辑进行编码。