37

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

APPLES = 1

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

但如果 mysettings.py没有定义那个值,那么访问settings.APPLES显然是行不通的。APPLES如果没有明确的设置,是否有某种方法可以定义使用的默认值settings.py

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

4

5 回答 5

33

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

from django.conf import settings

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


APPLES = get('APPLES', 1)

然后我需要访问 APPLES 我有:

from myapp import settings as myapp_settings

myapp_settings.APPLES

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

于 2011-04-08T23:02:45.963 回答
19

怎么样:

getattr(app_settings, 'SOME_SETTING', 'default value')
于 2015-04-07T18:37:42.787 回答
8

这里有两个解决方案。对于两者,您都可以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()

为整个项目配置默认值

在您的代码中使用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()

这个解决方案可能看起来更容易安装,但它并不能保证会返回好的默认值。如果多个应用程序在它们的 settings.py 中声明了相同的变量,您无法确定哪一个会返回您询问的默认值。

于 2015-08-25T22:00:13.370 回答
2

从迈克的回答开始,我现在将默认设置处理包装到一个具有易于使用界面的类中。

辅助模块:

from django.conf import settings

class SettingsView(object):
   class Defaults(object):
      pass

   def __init__(self):
      self.defaults = SettingsView.Defaults()

   def __getattr__(self, name):
      return getattr(settings, name, getattr(self.defaults, name))

用法:

from localconf import SettingsView

settings = SettingsView()
settings.defaults.APPLES = 1

print settings.APPLES

这将打印来自 的值django.conf.settings,如果未在此处设置,则打印默认值。此settings对象还可用于访问所有标准设置值。

于 2011-04-09T00:20:20.730 回答
0

我最近遇到了同样的问题,并创建了一个专门用于这种情况的 Django 应用程序。它允许您为某些设置定义默认值。然后它首先检查是否在全局设置文件中设置了设置。如果不是,它将返回默认值。

我已经对其进行了扩展,还允许对默认值进行一些类型检查或预先处理(例如,可以在加载时将点线类路径转换为类本身)

该应用程序可以在以下位置找到:https ://pypi.python.org/pypi?name=django-pluggableappsettings&version=0.2.0&:action=display

于 2015-09-29T14:45:49.793 回答