2011-04-08 88 views
21

Django文档mentions您可以将自己的设置添加到django.conf.settings。所以,如果我的项目的settings.py定义如何为自定义Django设置定义默认值

APPLES = 1 

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

但是,如果我的settings.py未定义该值,则访问settings.APPLES显然不起作用。如果在settings.py中没有明确的设置,是否有某种方法可以为APPLES定义默认值?

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

回答

24

在我的应用程序中,我有一个单独的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将检查那里第一次和返回值,如果属性被发现或使用应用程序设置文件中定义的默认值。

+0

难道这不是脆弱的吗?不依赖于在'app_settings.py'之前导入的项目'settings.py'? – Flimm 2016-05-04 14:01:27

1

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

助手模块:

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对象也可以用来访问所有的标准设置值。

+0

我认为应用程序的具体设置应明确命名,并与主要设置不同,以方便阅读。 – 2011-04-09 00:27:07

1

您可以检查该设置是否已定义,如果没有,则将其设置为默认值。例如,你可以定义一个辅助函数setting_default这样的:

from django.conf import settings 

def setting_default(name, default_value): 
    value = getattr(settings, name, default_value) 
    setattr(settings, name, value) 

然后在需要的设置(也许在models.py)的应用程序中使用这样的:

setting_default('APPLES', 1) 

谁是使用这个方式你应用程序不必做任何特别的事情。

10

如何只:

getattr(app_settings, 'SOME_SETTING', 'default value') 
+0

这比其他一些建议要简单得多,但如果您打算多次使用设置/变量来打破DRY概念,在这种情况下其他解决方案可能会起作用。食物的思考:) – daniel 2015-04-11 06:33:20

+0

它如何打破干燥? – Charlie 2015-04-13 02:20:06

+0

如果你打算在你的应用程序中多次使用SOME_SETTING,那么你必须在你使用它的任何地方放置这个'getattr(app_settings,'SOME_SETTING',default_value) – daniel 2015-04-13 02:23:57

5

这里有两种解决方案。对于您可以在您的应用程序中设置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中声明了相同的变量,则无法确定哪个应用程序将返回所要求的默认值。

0

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

我已经扩展它也允许一些类型检查或默认值的预处理(例如虚线类路径可被转换为类本身上负载)

该应用程序可以被发现在: https://pypi.python.org/pypi?name=django-pluggableappsettings&version=0.2.0&:action=display

相关问题