如何为自定义Django设置定义默认值

sth*_*sth 30 django default-value django-settings

Django文档提到您可以添加自己的设置django.conf.settings.所以,如果我的项目settings.py定义

APPLES = 1
Run Code Online (Sandbox Code Playgroud)

我可以settings.APPLES在该项目的应用程序中访问它.

但如果我settings.py没有定义该值,settings.APPLES显然访问将无效.APPLES如果没有显式设置,是否有某种方法可以定义默认值settings.py

我最好在模块/包中定义需要设置的默认值.

Mik*_*rez 28

在我的应用程序中,我有一个单独的settings.py文件.在该文件中,我有一个get()函数,它在项目的settings.py文件中查找,如果没有找到则返回默认值.

from django.conf import settings

def get(key, default):
    return getattr(settings, key, default)


APPLES = get('APPLES', 1)
Run Code Online (Sandbox Code Playgroud)

然后我需要访问APPLES我有:

from myapp import settings as myapp_settings

myapp_settings.APPLES
Run Code Online (Sandbox Code Playgroud)

这允许在项目settings.py中覆盖,getattr将首先检查那里并在找到属性时返回值或使用应用程序设置文件中定义的默认值.

  • 这不是脆弱吗?是否不依赖于在app_settings.py之前导入项目settings.py? (2认同)

Cha*_*lie 14

怎么样:

getattr(app_settings, 'SOME_SETTING', 'default value')
Run Code Online (Sandbox Code Playgroud)

  • 这比这里的其他一些建议简单得多,但是如果您打算多次使用设置/变量,那么您就打破了 DRY 概念,在这种情况下,其他解决方案可能会起作用。深思熟虑:) (2认同)

azm*_*euk 7

这是两个解决方案.对于这两种方法,您可以settings.py在应用程序中设置文件并使用默认值填充它们.

配置单个应用程序的默认值

使用from MYAPP import settings,而不是from django.conf import settings在你的代码.

编辑YOURAPP/__init__.py:

from django.conf import settings as user_settings
from . import settings as default_settings

class AppSettings:
    def __getattr__(self, name):
        # If the setting you want is filled by the user, let's use it.
        if hasattr(user_settings, name):
            return getattr(user_settings, name)

        # If the setting you want has a default value, let's use it.
        if hasattr(default_settings, name):
            return getattr(default_settings, name)

        raise AttributeError("'Settings' object has no attribute '%s'" % name)

settings = AppSettings()
Run Code Online (Sandbox Code Playgroud)

配置整个项目的默认值

使用from MYPROJECT import settings,而不是from django.conf import settings在你的代码.

编辑 MYPROJECT/MYPROJECT/__init__.py

import os, sys, importlib
from . import settings as user_settings

def get_local_apps():
    """Returns the locally installed apps names"""
    apps = []
    for app in user_settings.INSTALLED_APPS:
        path = os.path.join(user_settings.BASE_DIR, app)
        if os.path.exists(path) and app != __name__:
            apps.append(sys.modules[app])
    return apps

class AppSettings:
    SETTINGS_MODULE = 'settings'

    def __getattr__(self, setting_name):

        # If the setting you want is filled by the user, let's use it.
        if hasattr(user_settings, setting_name):
            return getattr(user_settings, setting_name)

        # Let's check every local app loaded by django.
        for app in get_local_apps():
            module_source = os.path.join(app.__path__[0], "%s.py" % self.SETTINGS_MODULE)
            module_binary = os.path.join(app.__path__[0], "%s.pyc" % self.SETTINGS_MODULE)
            if os.path.exists(module_source) or os.path.exists(module_binary):
                module = importlib.import_module("%s.%s" % (app.__name__, self.SETTINGS_MODULE))

                # Let's take the first default value for this setting we can find in any app
                if hasattr(module, setting_name):
                    return getattr(module, setting_name)

        raise AttributeError("'Settings' object has no attribute '%s'" % setting_name)

settings = AppSettings()
Run Code Online (Sandbox Code Playgroud)

此解决方案似乎更容易安装,但它不保证将返回良好的默认值.如果多个应用程序在settings.py中声明了相同的变量,则无法确定哪个应用程序将返回您询问的默认值.