- PVSM.RU - https://www.pvsm.ru -

Собственный модуль settings

Преамбула

Этот модуль родился в результате переосмысления (или недопонимания) мной вот этого пространного документа: Splitting up the settings file [1], размещённого на официальном сайте Django.

Постановка задачи

При старте веб-приложения на Django (как посредством запуска отладочного сервера, так и в качестве WSGI-приложения) фреймворк первым делом выполняет модуль, задающий начальные настройки проекта. Источник кода задаётся переменной окружения DJANGO_SETTINGS_MODULE [2]. При создании Django-проекта стандартным способом, например:

$ django-admin startproject myproject

создаётся и модуль настроек. Это файл ‘myproject/myproject/settings.py’. Изменяя и дополняя его, программист настраивает проект, добавляет в него собственные и сторонние компоненты и т. д.

В простых проектах, разрабатываемых одним бэкенд-программистом, бывает вполне разумно ограничиться таким модулем настроек. Однако по мере роста проекта возникают следующие проблемы:

  1. Настройки проекта для развёртывания в боевой или тестовой среде очень отличаются от настроек, с которыми проект запускают разработчики. Например, в бою приложение требует «большой» SQL-сервер (PostgreSQL или MySQL) и дополнительную базу данных «ключ-значение» для хранения кэшируемых данных (memcached или Redis), в то время как разработчик на своём компютере привык обходиться SQLite. Зато настройки разработчика включают дополнительные модули для отладки проекта (например, debug_toolbar), которые не должны попаcть в production.
  2. Переменные, устанавливающие режим отладки в Django (DEBUG [3], TEMPLATE_DEBUG и др.), а также аналогичные переменные для сторонних компонентов, должны быть включены при разработке и выключены в продакшне. За этим довольно муторно следить при коммитах.
  3. В модуле settings хранятся чувствительные данные (SECRET_KEY [4], секреты/пароли для аутентификации приложения на различных сервисах и т. д.), которые становится небезопасно хранить в одном репозитории с кодом. Это особенно важно для open source-проектов, а также для крупных проектов, в которых доступ к кодовой базе имеет много разработчиков.

Проблемы 1 и 2 частично решает хранение в репозитории нескольких файлов настроек на разные случаи жизни и выбор нужного через установку переменной DJANGO_SETTINGS_MODULE. Недостаток такого решения в том, что данные в этих файлах почти полностью дублируются. По мере развития проекта разработчик обязан вносить одинаковые изменения в несколько различных файлов конфигурации, что утомительно, приводит к ошибкам и т. д., − короче говоря, противоречит принципу DRY [5].

Решение

Мой модуль settings обладает максимальной обратной совместимостью с дефолтовым ‘myproject/myproject/settings.py’: все ссылки на myproject.settings, если они действительно необходимы, остаются в силе. В то же время моё решение позволяет администратору проекта обезопасить приватные данные, а разработчикам − организовать себе наиболее комфортную среду на собственный вкус, независимо от коллег. Дополнительным плюсом является механизм наследования настроек: в локальных настройках можно получить доступ к общим настройкам.

Минус: для хранения локальных настроек нужно придумать какой-то отдельный метод, так как репозиторий использовать не получится. Решение этого вопроса обычно лежит в организационной плоскости: передавать секрет от более опытных коллег менее опытным, публиковать сэмпловый ‘local.py’ в приватном разделе wiki и т. п.

Зато мой метод крайне прост и быстр, не вмешивается в процесс парсинга настроек фреймворком и не создаёт лишних сущностей вроде специальных *.ini/*.conf-файлов с парсерами, классов настроек или модифицирующих настройки функций.

Hands-on

Вот последовательность действий по «апгрейду» классического модуля настроек (подразумевается, что код хранится в git-репозитории):

  1. Создайте в каталоге главного приложения подкаталог ‘settings’. Путь к нему будет выглядеть так: ‘myproject/myproject/settings/’.
  2. Переместите ваш старый ‘settings.py’ в созданный в п. 1 каталог ‘myproject/myproject/settings/’ и переименуйте его в ‘common.py’. Будем ссылаться на этот файл в дальнейшем как на «общие настройки».

    Если вы используете в проекте относительные пути от файла настроек, увеличьте глубину вложенности на один каталог. Например, код типа:

    BASE_DIR = dirname(dirname(abspath(__file__)))
    

    должен превратиться в

    BASE_DIR = dirname(dirname(dirname(abspath(__file__))))
    
  3. Создайте файл ‘myproject/myproject/settings/local.py’. В него сразу добавьте следующий код:
    from myproject.settings.common import *
    

    Вы можете добавить локальные настройки, начиная со следующей строки.

    Например, если вы − разработчик, и хотите использовать замечательный инструмент Django Debug Toolbar [6], вы можете добавить следующую строку:

    INSTALLED_APPS += ('debug_toolbar', )
    
  4. Создайте файл ‘myproject/myproject/settings/__init__.py’ и внесите в него следующий код:
    try:
        from myproject.settings.local import *
    except ImportError:
        from myproject.settings.common import *
    

    Этот вариант рассчитан на тот случай, когда настройки, содержащиеся в common.py, вполне достаточны для того, чтобы проект запустился. Это вряд ли будет соответствовать истине в большом проекте. Как минимум, из общих настроек следует изъять SECRET_KEY по соображениям безопасности.

    Если без файла локальной конфигурации запуск проекта не имеет смысла, можно не пытаться обойтись глобальными настройками, а выбросить исключение:

    try:
        from myproject.settings.local import *
    except ImportError:
        raise Exception('Please create local.py file')
    
  5. Добавьте файл ‘myproject/myproject/settings/local.py’ в исключения git. Это последний, но от этого не менее важный шаг.

Готово! Мы разбили файл настроек на общую, прототипную часть (common.py), и локальную часть, наследующую настройки от общей (local.py). Теперь всё дело за правильной декомпозицией настроек.

Автор: Tanner

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/113358

Ссылки в тексте:

[1] Splitting up the settings file: https://code.djangoproject.com/wiki/SplitSettings/

[2] DJANGO_SETTINGS_MODULE: https://docs.djangoproject.com/en/1.8/topics/settings/#envvar-DJANGO_SETTINGS_MODULE

[3] DEBUG: https://docs.djangoproject.com/en/1.9/ref/settings/#std:setting-DEBUG

[4] SECRET_KEY: https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-SECRET_KEY

[5] DRY: https://ru.wikipedia.org/wiki/Don’t_repeat_yourself

[6] Django Debug Toolbar: http://django-debug-toolbar.readthedocs.org/

[7] Источник: https://habrahabr.ru/post/277937/