每个应用的Django设置 - 最佳实践?

57 投票
5 回答
28728 浏览
提问于 2025-04-17 22:10

这和这个问题有点关系
为什么Django的设置对象是一个LazyObject?

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

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

这里一般的最佳实践是什么呢?
应用的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的懒加载设置对象?

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')

然后每个app/views.py只需通过django.conf的settings来使用proj/settings.py?

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

显然还有很多其他的组合方式,但我想我的意思已经很清楚了。
提前谢谢你。

5 个回答

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

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

# 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')

这个配置解析器的详细介绍可以在 这里 找到。它用起来挺方便的,但绝对不是唯一的选择。

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
10

自从Django 1.7版本开始,出现了一种基于Django的应用配置结构!你可以在这里找到详细的解决方案。

在这个新结构中,通常你会在项目中的应用文件夹里有一个叫做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

其他的apps.py文件在你的Django应用文件夹中也是类似的。

很重要的一点是,你需要导入你在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
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"

撰写回答