Статьи

Расширение настроек Django для реального мира

Первоначально написано Адамом Нельсоном

. Базовая установка Django хранит свои глобальные переменные в файле settings.py. Это идеально подходит для простого развертывания, поскольку позволяет разработчику легко перезаписывать переменные Django, такие как INSTALLED_APPS или SESSION_ENGINE. Вы просто обновляете переменную следующим образом:

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'

Внутри оболочки вы можете увидеть результат:

./manage.py shell
>>> from django.conf import settings
>>> settings.SESSION_ENGINE
'django.contrib.sessions.backends.cache'

У многих людей есть две среды, в которых они работают, и поэтому в конце типичный файл settings.py будет выглядеть примерно так:

try:
    from local_settings import *
except ImportError:
    pass

Это перезаписывает переменные из файла local_settings.py, переопределяя любые существующие переменные в файле settings.py. Попробуй. Добавьте приведенный выше код импорта в файл settings.py и создайте новый файл с именем local_settings.py в том же каталоге, что и файл settings.py, и добавьте к нему следующее:

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'

Теперь, если вы войдете в оболочку, как вы делали выше, и запросите настройки. SESSION_ENGINE, вы получите django.contrib.sessions.backends.cache. Это очень удобно, потому что в типичной ситуации у вас может быть файл settings.py, который работает для всех ваших сред, а затем файл local_settings.py для каждой среды, который переопределяет значения переменных.

Проблемы с файлами стандартных настроек

К сожалению, в этом сценарии переменные из файла settings.py не могут быть интерпретированы в файле local_settings.py, и поэтому вы не можете сделать что-то вроде этого:

INSTALLED_APPS += ('debug_toolbar',)

В этой ситуации вы получите NAME_ERROR, в котором INSTALLED_APPS не определено, а не (‘django.contrib.auth’, ‘debug_toolbar’,).

Скромное предложение

Что мы делаем в Yipit — это помещаем все наши переменные в каталог настроек:

settings/
__init__.py (where the variable for all environments are)
active.py (optional - defines the environment we're in - not under version control)
development.py (shared by all the development environments)
production.py (live site)

Это позволяет нам создать файл init .py для всех переменных, которые одинаковы во всех средах. Инициализации файл .py не требует импорта ( за исключением того, что вы , возможно , потребуется от самого Python или других библиотек). Затем каждый файл импортируется из init .py так, как вы можете себе представить:

production.py:

from settings import *
#Alter or add production specific variables

development.py:

from settings import *
#Alter or add development specific variables

active.py:

from settings.development import *
#This file denotes which environment we're in.
#This active.py file creates a development environment

Примечание: если вы не очень хорошо знакомы с Python, «из настроек» открывает настройки / init .py.

В более сложных сценариях вы также можете унаследовать настройки от файлов, отличных от настройки / init .py, и эта система полностью поддерживает эту опцию. Например, у вас могут быть файлы settings / staging.py, которые извлекаются из файла settings / init .py, а затем settings / development.py могут извлекать данные из стадии подготовки. Это действительно зависит от вас.

У этого подхода есть некоторые недостатки, в частности, то, что вы не можете динамически изменять переменные — но это на самом деле не имеет значения настроек. Теперь вы можете изменять переменные для каждой среды следующим образом (например, в development.py):

INSTALLED_APPS += ('debug_toolbar',)

Который установит INSTALLED_APPS как (‘django.contrib.auth’, ‘debug_toolbar’,). Вот наш файл manage.py:

#!/usr/bin/env python
import sys
import traceback
from os.path import abspath, dirname, join

from django.core.management import execute_manager

SETTINGS_ACTIVE_CONTENTS = "\033[1;32mfrom settings.local import *\033[1;33m"
try:
    from settings import active as settings
except ImportError, e:
    print '\033[1;33m'
    print "Apparently you don't have the file settings/active.py yet."
    print "Create it containing '%s'\033[0m" % SETTINGS_ACTIVE_CONTENTS
    print
    print "=" * 20
    print "original traceback:"
    print "=" * 20
    print
    traceback.print_exc(e)
    sys.exit(1)

sys.path.insert(0, abspath(join(dirname(__file__), "../")))
sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))

if __name__ == "__main__":
    execute_manager(settings)

Последние мысли

Если мы внесем дополнительные изменения в нашу конфигурацию настроек, мы сделаем следующий пост. Некоторые модификации, которые мы рассматриваем:

  • Использование Chef для хранения многих системных параметров конфигурации (имен пользователей, адресов компьютеров и т. Д.), Чтобы переместить эту информацию с уровня приложений на уровень среды.

  • Создание дополнительного файла настроек, который импортирует active.py для рассчитанных настроек. Например, если база данных реплики для чтения не была объявлена, но приложение ожидает ее, база данных по умолчанию будет действовать как реплика для чтения.

Если у вас есть другой способ обработки настроек, мы будем рады услышать ваши комментарии в комментариях ниже.

Адам Нельсон — технический директор Yipit.