使用django-configurations拆分配置文件

时间:2013-11-12 19:29:42

标签: python django configuration split settings

为Django构建的包,django-configurations使用面向对象的模式扩展基于模块的设置加载。

该软件包使用DJANGO_SETTINGS_MODULEDJANGO_CONFIGURATION环境变量来识别设置文件并分别加载适当的配置。

我想将配置(每个对象)拆分成单独的文件,但遇到困难。

目前;

    settings/settings.py

想改变;

    settings/base.py  
    settings/local.py  
    settings.production.py

有没有人设法实现这一目标,或者知道一个可行的解决方案来实现这一目标?

3 个答案:

答案 0 :(得分:2)

您可以设置一个环境变量来指定要使用的设置文件,然后在manage.pywsgi.py中执行类似的操作

config_mode = os.getenv('DJANGO_CONFIG_MODE', 'base')

config_dict = {
    'base': 'settings.base'
    'local': 'settings.local'
    'production': 'settings.production'
}

os.environ.setdefault('DJANGO_SETTINGS_MODULE', config_dict[config_mode])

# or if you prefer not using a dictionary or if-else blocks, you could
# set the settings file name you wish to use as the DJANGO_CONFIG_MODE environment
# variable and use that directly

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.{0}'.format(config_mode))

您可能还想在不同的设置文件中指定模式,以便您的代码在不同的模式下可以有不同的行为。

CONFIG_MODE = 'base'   # or 'local' or 'production'

在各种设置文件中,并根据需要在代码库中使用它。

答案 1 :(得分:2)

DJANGO_CONFIGURATION变量引用configurations.Configuration子类。正如usage patterns上的文档中所描述的那样,我们的想法是为多个DRYer Mixin / Class工作流程方案维护多个设置文件的繁琐开销。我知道不得不改变manage.pywsgi.py,但你得到了很多。

# example settings.py
from configurations import Configuration, values

# Build up some mixin classes for related or app-specific settings:
class AppsMixin(object):
    DJANGO_APPS = (
        'django.contrib.auth', 'django.contrib.contenttypes',
        'django.contrib.sessions', 'django.contrib.messages', 
        'django.contrib.staticfiles', 'django.contrib.sites',
        'django.contrib.flatpages', 'django.contrib.sitemaps',
        'django_extensions'
    )
    ADMIN_APPS = ('filebrowser', 'grappelli', 'django.contrib.admin',)
    DEV_APPS = ('django.contrib.admindocs', 'debug_toolbar',)
    DEFAULT_APPS = (
        'tagging', 'imagekit',
        'tinymce', 'ajax_select',
        'crispy_forms', #...
    )

    @property
    def INSTALLED_APPS(self):
        """ Control application ordering dynamically """
        OUT_APPS = self.DJANGO_APPS + self.ADMIN_APPS
        if self.DEBUG:
            OUT_APPS += self.DEV_APPS
        return  OUT_APPS + self.DEFAULT_APPS

class AuthURLMixin(object):
    LOGIN_REDIRECT_URL = 'site-login-success'
    LOGIN_URL = '/auth/login/'
    LOGOUT_URL = '/auth/logout/'

class CrispyFormsMixin(object):
    """ django-crispy-forms specific settings """
    CRISPY_TEMPLATE_PACK = 'bootstrap3'

    @property
    def CRISPY_FAIL_SILENTLY(self):
        return not self.DEBUG

class Base(AppsMixin, AuthURLMixin, CrispyFormsMixin, Configuration):
    """ Your equivalent for settings/base.py """
    pass

class Local(Base):
    """ ~ settings/local.py """
    DEBUG = True
    TEMPLATE_DEBUG = DEBUG
    # Custom setting that lets subclasses or your apps
    # check which subclass is active.
    STAGING = False
    # Enable a setting to be defined in os.environ, with a sensible default
    # Don't forget the 'DJANGO_' prefix (e.g. DJANGO_TIME_ZONE) 
    TIME_ZONE = values.Value('America/New_York')
    HTTPS_ONLY = False
    # Stash the secret key in os.environ as DJANGO_SECRET_KEY
    SECRET_KEY = values.SecretValue()

    @property
    def CSRF_COOKIE_SECURE(self):
        """ chained dynamic setting """
        return self.HTTPS_ONLY

    @property
    def SESSION_COOKIE_SECURE(self):
        """ chained dynamic setting """
        return self.HTTPS_ONLY

class Staging(Local):
    """ This class is used for testing before going production """
    STAGING = True 
    TIME_ZONE = values.Value('America/Phoenix')
    #...

class Prod(Staging):
    """ ~ settings/production.py """
    DEBUG = False
    STAGING = False
    HTTPS_ONLY = True

然后,从您的笔记本电脑:

/path/to/project/$ python manage.py shell --configuration=Local
>>>from django.conf import settings
>>>settings.DEBUG, settings.STAGING, settings.TIME_ZONE
(True, False, 'America/New_York')    

从远程服务器:

/path/to/remote/project/$ python manage.py shell --configuration=Staging
>>>from django.conf import settings
>>>settings.DEBUG, settings.STAGING, settings.TIME_ZONE
(True, True, 'America/Phoenix')

一旦一切都很完美,请转到全系统:

# /etc/environment
DJANGO_SETTINGS_MODULE=thisproject.settings
DJANGO_CONFIGURATION=Prod

现在三个文件的问题已经解决了一些额外的问题:

  • 动态属性允许您切换或插入任何数字 通过实例方法立即进行相关设置。
  • 可以通过mixins引入和删除大量设置。
  • 敏感键设置不受源代码管理。

所以,可以可以想象这些文件中的三个每个都有三个类,但为什么不用九个呢?

答案 2 :(得分:0)

您可以尝试使用单个设置文件并在其中设置条件。因此,当您在本地运行它时,它会设置与远程运行时不同的参数。例如:

import os

DEVELOPMENT_MODE = not os.path.isfile('/mnt/SERVER')

DEBUG = DEVELOPMENT_MODE
TEMPLATE_DEBUG = DEBUG

上面检查机器上的文件' / mnt / SERVER',我的服务器有这个文件,我的笔记本没有。它是一个空文件,只是一个占位符。但它在我的设置中设置了一个标志,我可以这样使用:

if DEVELOPMENT_MODE:
  CONST_URL = 'http://localhost:8000'
else:
  CONST_URL = 'http://www.website.com'

我多年来一直在使用它,优点是我的apache,wsgi和manage.py保持不变。