Django的应用程序设置-最佳实践?

57

这与这个问题有些关联:
为什么 Django 的 settings 对象是一个 LazyObject?

在我的 Django 项目中,我有几个应用程序。每个应用程序都可以有自己的复杂设置文件。

proj/
    proj/
         settings.py
    app/
         settings.py
         views.py

这里的通用最佳做法是什么?
app/settings.py 应该怎么做?

from django.conf import settings
APP_SETTING= lambda: settings.getattr('APP_SETTING', 'custom_value')
PROJ_SETTING= lambda: settings.PROJ_SETTING

然后在 app/views.py 中执行

import .settings 
X = settings.APP_SETTING
Y = settings.PROJ_SETTING

我应该按照 Django 编码风格修改 app/settings.py 中的 Django lazy settings 对象吗?

from django.conf import settings
# not even sure how I would check for a default value that was specified in proj/settings.py
settings.configure(APP_SETTING='custom_value')

然后每个应用程序/ views.py 通过django.conf设置仅使用proj/settings.py,对吗?

from django.conf import settings
X = settings.APP_SETTING
Y = settings.PROJ_SETTING

显然还有很多其他的组合方式,但我认为我的意图很清楚。
提前感谢。


1
https://dev59.com/q1XTa4cB1Zd3GeqP2YNP - RexE
谢谢你提供的链接。你个人通常做什么? - w--
5个回答

21

最简单的解决方案是使用你自己提到过的 getattr(settings, 'MY_SETTING', 'my_default') 技巧。然而,在多个地方都需要这样做可能会有些繁琐。

更好的建议是使用每个应用程序前缀,如 MYAPP_MY_SETTING

然而,有一个 Django 应用程序可以省去 getattr 并为您处理前缀。请参见 http://django-appconf.readthedocs.org/en/latest/

通常情况下,您会为每个应用程序创建一个名为 conf.py 的文件,并编写以下内容:

from django.conf import settings
from appconf import AppConf

class MyAppConf(AppConf):
    SETTING_1 = "one"
    SETTING_2 = (
        "two",
    )

在你的代码中:

from myapp.conf import settings

def my_view(request):
    return settings.MYAPP_SETTINGS_1  # Note the handy prefix

如果您需要自定义站点设置,只需在站点的 settings.py 中添加一条常规条目即可:

如下:

MYAPP_SETTINGS_1 = "four, four I say"

1
"django-appconf" 真的非常好。 - mbaechtold
Django为每个新应用程序创建apps.py文件。该文件包含一个继承自AppConfig的类。这是否可以用于相同的目的? - A. B
1
不,那是一个不同的appconfig。根据https://pypi.python.org/pypi/django-appconf,“换句话说,它们解决了与django-appconf相关但不同的用例,并且不能轻易地用作替代品。名称的相似性纯属巧合。” - Reinout van Rees
我不得不使用django-appconf,因为当我一次性运行所有测试时,getattr方法会导致我的测试失败。 - adonig

10
自Django 1.7版本以来,有一个基于Django的应用程序配置结构!您可以在此处找到描述性解决方案here 在这个新的结构中,通常情况下,您可以在应用程序文件夹中拥有一个apps.py文件,这些文件夹嵌入在项目中,就像这样:
proj/
    proj/
         settings.py
    app1/
        apps.py
        views.py
    app2/
        apps.py
        views.py

app1/apps.py文件可能包含以下内容:

from django.apps import AppConfig


class App1Config(AppConfig):
    # typical systemic configurations
    name = 'app1'
    verbose_name = 'First App'

    # your desired configurations
    OPTION_A = 'default_value'
    APP_NAMESPACE = 'APP'
    APP_OPTION_B = 4

你可以像这样将 app2/apps.py 命名为其他名称:

from django.apps import AppConfig


class App2Config(AppConfig):
    # typical systemic configurations
    name = 'app2'
    verbose_name = 'Second App'

    # your desired configurations
    OTHER_CONFIGURATION = 'default_value'
    OPTION_C = 5

以同样的方式为 Django 应用程序文件夹中的其他 apps.py 文件进行操作。

您需要按以下方式导入包括 apps.py 的应用程序:

# proj/settings.py

INSTALLED_APPS = [
    'app1.apps.App1Config',
    'app2.apps.App2Config',
    # ...
]

现在,您可以通过以下方式访问所需的基于应用程序的配置:

from django.apps import apps
apps.get_app_config('app1').OPTION_A

9
我觉得这个解决方案并没有回答 OP 的问题——它不能让你在项目设置中覆盖默认应用程序配置。使用此处的代码,你总是会得到应用程序本地默认配置设置的值。 理想情况下,像 https://pypi.python.org/pypi/django-appconf 这样的东西将被集成到 django.apps.AppConfig 中,这样一个简单的标准解决方案就在 Django 中了。 - powderflask

6

我不确定最佳实践,但我没有任何问题遵循以下格式:

proj/settings.py

OPTION_A = 'value'

# or with namespace
APP_NAMESPACE = 'APP'
APP_OPTION_B = 4

app/settings.py

from django.conf import settings
from django.utils.functional import SimpleLazyObject

OPTION_A = getattr(settings, 'OPTION_A', 'default_value')

# or with namespace
NAMESPACE = getattr(settings, APP_NAMESPACE, 'APP')
OPTION_B = getattr(settings, '_'.join([NAMESPACE, 'OPTION_B']), 'default_value')
OPTION_C = getattr(settings, '_'.join([NAMESPACE, 'OPTION_C']), None)
if OPTION_C is None:
    raise ImproperlyConfigured('...')

# lazy option with long initialization
OPTION_D = SimpleLazyObject(lambda: open('file.txt').read())

app/views.py

from .settings import OPTION_A, OPTION_B
# or
from . import settings as app_settings
app_settings.OPTION_C
app_settings.OPTION_D  # initialized on access

1

你可以使用django-zero-settings,它允许你定义默认值和用户设置的key,然后它会处理用户的覆盖。

它还可以自动导入你的设置,有能力处理已删除的设置,并且也可以预检查设置。

例如,定义你的设置:

from zero_settings import ZeroSettings

app_settings = ZeroSettings(
    key="APP",
    defaults={
        "TOKEN": "token"
    },
)

然后你可以像这样使用它:

from app.settings import app_settings

print(app_settings.TOKEN)

1
为了未来读者的利益,我要指出以下几点:1)zero_settings是本帖作者编写的。2)它在过去12个月内没有更新。3)它是根据GPL发布的 - 这意味着如果您选择使用zero_settings,则需要使您自己的项目完全开源。 - Dr Phil
感谢@DrPhil的评论,实际上我太忙了,没来得及更新。但是关于许可证的问题,你认为怎么做更好?如果需要的话,我可以更改许可证或删除它。我不想强迫任何人去做任何事情。 - aasmpro
你好。我不太确定该给您许可证方面的建议。当然,这是您的决定。快速搜索GPL、Apache和MIT之间的区别应该能为您提供高层次的差异。由于我的项目是闭源的,所以我只能使用Apache或MIT这样的开放源代码许可证。 - Dr Phil
1
谢谢@DrPhil!那我会更改为另一个许可证,你能使用这个包并测试它吗?不知道你是否认为有什么需要改进的地方或者是否有兴趣贡献呢?你可以在我的个人资料中找到与我联系的链接 ;) - aasmpro

0

我的网站刚刚开始,我想要一个最简单但是灵活的配置解决方案。这就是我找到的。

# in the end of the site's settings.py
. . .
# Custom settings
MYAPP_CONFIG_FILE = "/home/user/config/myapp_config.ini"

在我的应用程序的models.py文件中:
from django.conf import settings
import configparser

config = configparser.ConfigParser()
config.read(settings.MYAPP_CONFIG_FILE, encoding='utf_8')

这个配置解析器在这里有描述。它足够方便,但绝不是唯一的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接