在运行时更改 Django 设置

Posted

技术标签:

【中文标题】在运行时更改 Django 设置【英文标题】:Changing Django settings at runtime 【发布时间】:2011-09-25 14:28:15 【问题描述】:

我想向管理界面公开一些(特定于应用程序的)设置,以便用户可以轻松地更改它们而不必重新启动 Django。

我该怎么办?

我查看了http://djangopackages.com/grids/g/live-setting/ 上的应用程序(顺便说一句,django-constance 是最吸引人的),但实际上所有这些应用程序所做的是将值存储在数据库中,提供更改它们的 Web 界面和缓存。前两个功能不是已经内置到 Django 中了吗?

我看到的最大缺点是没有一个应用程序可以直接替换这些设置的旧位置 (settings.py),并且需要我迁移到它们的符号,并且经常添加另一个上下文处理器来访问它们在模板中。

我不能这样做吗?

    为我的设置创建一个模型(这为我提供了各种类型和验证) 实例化一个这样的对象来保存我的设置(这允许用户在管理界面中编辑它们) - 我可以像其他模型一样将默认设置转储为固定装置 包装 settings.py 以便对我的设置进行数据库查询 - http://www.loose-bits.com/2011/04/extending-django-settings-with-derived.html

从我目前幼稚的角度来看,我看到的唯一缺点是:

    添加或更改可用设置需要架构迁移(南)。 - 我可以忍受。 我有一个可能有多个实例的模型,但实际上只需要一个单例。 - 在某些时候这实际上可能是一个有用的功能。 性能/缓存:看看http://code.djangoproject.com/svn/django/trunk/django/conf/,我必须在设置包装器和/或模型中加入一点小技巧,以便模型更改清除或更新缓存值。 - 似乎不是火箭科学。 在另一个项目中做同样的事情需要再次进行类似的工作。 - 我认为 settings.py 中的单个字典常量,用于查找的模型名称和字段名称是唯一不同的。

这难道不是两全其美 - 运行时管理员(及其所有特权)、数据库后端、缓存以及我的任何设置。USED_TO_BE_IN_SETTINGS_DOT_PY 不需要任何更改。我错过了什么吗?

【问题讨论】:

如果你想像以前那样使用django.conf.settings,除了破解 Django 本身之外,你没有办法实现你想要的。您应该至少将调用迁移到设置(代码迁移)以使用外部库提供的设置对象。 感谢您的评论。使用 settings.py 包装器(请参阅 URL)并没有破解 Django 本身恕我直言,这只是 settings.py 从项目返回设置的方式(但是它们随后被处理)。添加另一个应用程序并重写所有导入似乎比我的方法更有效,我想知道为什么这种方法不够或不能达到我目前预测的效果...... 也许我误解了你,但是示例包装器不一样,你仍然需要将导入重写为设置吗?不久前我写了一个这样的应用程序(公司内部,所以很遗憾我还不允许发布它),它写了一个围绕设置的包装器。而不是from django.conf import settings,那么在我使用它的应用程序中它将是from my_settings_app import settings。在这种情况下,最后一个是访问 db/cache 并在它们都不存在时回退到默认设置。这不是你的意思吗? 这就是我的意思,但我还不明白为什么我不能对 settings.py 本身做同样的事情——它是一个 python 模块。 (供将来参考)问题中的网址不再有效,但有效(截至目前)网址为djangopackages.com/grids/g/live-setting 【参考方案1】:

不能直接修改settings.py文件 例如: 如果你想在运行时更改数据库,你应该分离数据库的配置

# Projecr_name/user_database.py
user_database = 
'default': 
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'name',
    'USER': 'admin',
    'PASSWORD': '111111',
    'HOST': '127.0.0.1',
    'PORT': '3306'
,
'user_db': 
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'user1',
    'USER': 'admin',
    'PASSWORD': '22222',
    'HOST': '127.0.0.1',
    'PORT': '3306'


# Projecr_name/settings.py
from .user_database import user_database
...
DATABASES = user_database
...

在你的逻辑视图中调用

# view.py
from ../Projecr_name/user_database import user_database
class Some(...):
    def Some(request):
    user_database['user_db']['NAME']='user2'

那么你可以在运行时使用这种方式更改任何设置

【讨论】:

【参考方案2】:

您可以使用settings模块的推荐.configure()方法:

from django.conf import settings
settings.configure(DEBUG=True)

settings 模块具有额外的便利功能。检查docs。

【讨论】:

这将启动raise RuntimeError('Settings already configured.') Same raise RuntimeError('Settings already configured.')【参考方案3】:

来自 Django 1.8 文档:

You shouldn’t alter settings in your applications at runtime.

【讨论】:

感谢 Chuck,请参阅我对 André Caron 回答的评论。文档已经声明多年来code.djangoproject.com/ticket/14628 - 在我的情况下(五年前发布的问题)我的意思是我自己的应用程序特定设置,而不是 Django 内置设置。【参考方案4】:

老实说,当我分析他的代码时,我得到了更多的 Django。在 1.4.5 版本中做到了(按照下面的模块):

myproject\manage.py

django\core\management__init__.py ## 方法 - execute_manager

django\conf__init__.py ## 类 - LazySettings; attr - _wrapped

django\utils\functional.py ## class LazyObject;重要方法—— 新方法代理

功能选项,但它有其风险。在 python 中,“_”认为该属性是受保护的。

from django.conf import settings

settings._wrapped.INSTALLED_APPS = () ## *really work*

在以下项目中:https://github.com/alexsilva/DJPlugins 您可以看到此变量在运行时被修改。该项目的想法已经开始实施。

【讨论】:

更改全局变量(作为设置的情况)将有利于单个进程,但如果您正在运行具有多个工作人员的生产环境(每个工作人员都有自己的全局副本)则不够好变量) 它可以帮助我测试我需要删除属性以检查是否会显示缺少的 raise,谢谢!【参考方案5】:

DATABASES 是一个字典。所以你可以如何操作字典:

import django.conf as conf

conf.settings.DATABASES['default']['NAME'] = 'novo_banco'

【讨论】:

问题是 Django 什么时候读取这个来创建django.db.connections。因为在那之后你最终会与 ORM 不同步。 这个 olny 允许我在执行时间进行编辑,而不是持久地。当我重新启动服务时,该值恢复到旧的。 不建议这样做。你可以在 Python 中,但不应该在 Django 中。 Python 允许您执行诸如访问“__foo”方法之类的事情,这些方法旨在“私有”。你可以,但这并不好,你的代码总有一天会坏掉。 Django 设置被认为是不可变的。 不行~!我还在寻找另一种选择!【参考方案6】:

看一看:https://bitbucket.org/bkroeze/django-livesettings *Django-Livesettings 是从Satchmo Project_ 拆分出来的一个项目。它提供了通过管理界面配置设置的能力,而不是通过编辑“settings.py”。*

也许对你有帮助。

【讨论】:

看看djangopackages.org/grids/g/live-setting 链接在 OP 的问题中,它列出了所有执行此功能的 Django 包。【参考方案7】:

AFAIK,Django 设置应该是不可变的。造成这种情况的原因有很多,最明显的是 Django 不知道服务器的执行模型(prefork / 多线程)。

此外,您不能从 Django 模型加载设置本身,因为需要先加载设置,然后才能在 ORM 中使用任何内容。

所以,基本上,你有两个解决方案:

您可以使用任何较低级别的数据库访问机制从数据库中引导设置来加载它们;或 您可以在其他模型中定义您的设置,并在需要时直接获取它们。

第一个是令人难以置信的 hack,我不建议这样做。第二种更直接、更干净,但需要你改变你的习惯(from django.conf import settings)。

第二种方法可能是您链接到的第 3 方应用所实现的。

【讨论】:

感谢您的评论。一些 Django 设置可以在运行时更改,尽管它目前没有记录 - code.djangoproject.com/ticket/14628 - 我的意思是真正的应用程序特定设置(想想用于计算的业务策略、百分比、日期等)。我只想排除那些。我提到的包装器的想法是 django.conf.settings 仍然可以使用,尽管值在数据库中。 嗨,我迟到了。但是有什么方法可以更改管理模块的一个特定设置变量。意味着我希望当我打开管理模块时,变量应该是“真”,否则是“假”

以上是关于在运行时更改 Django 设置的主要内容,如果未能解决你的问题,请参考以下文章

Django:啥时候运行makemigrations?

运行python程序时调试器不工作

运行显式创建表的迁移时未创建 Django 表。

带有 django-nose 的 Django:两个相同的设置文件,在运行测试命令时具有不同的行为

为啥 Django makemigrations 每次运行时都会检测到由于 help_text/verbose_name 属性中的重音而导致的更改?

WPF:在运行时更改配置文件用户设置?