Pull to refresh

Comments 22

UFO just landed and posted this here
Прошу прощения, промахнулся по ссылке. Ответ ниже.
Встречал в дикой природе django-environ. Забраковал его, и вот почему.

  1. Он требует переработать файл настроек согласно документации. В моём варианте в settings.py вносятся очень незначительные изменения, можно даже оставить его на первых порах без изменений.
  2. Он вводит отдельный формат хранения настроек. Мой метод, как я уже писал, лишних сущностей не создаёт.

А файл с секретами так и так руками копировать надо. В общем, незачот.

Также можно все настройки хранить в папке settings в виде отдельных файлов(apps.py, middlewares.py, celery.py и тд.)
Да, такой подход имеет место быть, но меня интересовало именно разделение настроек на глобальную и локальную части, а не по какому-то иному принципу. Если инклюдить всё в инит, теряется возможность порождать локальный сабсет настроек от глобального.
UFO just landed and posted this here
Нет, мне однозначно не нужны в проекте лишние классы и парсеры. Это неоправданные накладные расходы. В моём случае все потери сводятся к одному ‘import’, и я хотел бы на этом остановиться. Ну, в крайнем случае − несколько ‘import’.

а у вашем варианте придеться дублировать константы в local.py файле

Не понял этого момента. Какие именно константы придётся дублировать в local.py? Я же показываю в статье, что его содержимое ничего не дублирует, а только уточняет.
UFO just landed and posted this here
Разумеется, если продакшн использует одну СУБД, а девелопер − другую, то в local.py на сервере придётся определить одни DATABASES, а в local.py на машине девелопера − другие. Но если у нас имеются, например, 20 девелоперов, которые одинаковым способом используют SQLite и два продакшн-сервера с разными базами данных, то можно определить настройки трижды: для разработчиков − в common.py, а для серверов − в их персональных local.py.

Так же и с django-environ, как я понял: в env-файле будут храниться одни настройки, а в settings.py − другие.
UFO just landed and posted this here
То есть проблема в том, что у меня “DATABASES = {…}” будет написано не один раз, а несколько? Ну, это я точно переживу. =)
А файл с секретами так и так руками копировать надо. В общем, незачот.

На хероку, например, настройки в админке заполняются. Никакие файлы .env с настройками не нужно иметь в репозитории.
Недостаток такого решения в том, что данные в этих файлах почти полностью дублируются

А зачем их дублировать?
Создали base_settings, там все что дублируется записали или прописали настройки по умолчанию

Потом создали production_settings:

from base_settings import *

DEBUG = False

и debug_settings:

from base_settings import *

DEBUG = True

Если я не ошибаюсь такой же путь рекомендуют в Django Two Scope(Там про это точно есть отдельная глава)
Говоря о дублировании, я имел в виду вот этот и подобные варианты. Вариант с общими/частными настройками уже ближе к тому, что использую я. “Two Scoops of Django” не читал. :(
Я использую файлик settings.yaml, в котором переопределяю все константы типа пароля к базе и тп. В settings.py просто читается файл и импортруется в globals() все что найдет, втч с сохранением структуры если хэш.
Файлик лежит не в папке проекта, а в /usr/local/etc/ и права на доступ имеет только тот пользователь, под которым работает приложение. В принципе, можно класть и в home.

Хранить любые неверсионируемые файлы в папке проекта не очень люблю, поскольку при деплое обычно заменяется существующая папка новой — и все (или просто симлинк меняется). Бегать перекладывать файлики — это еще вспомнить их надо, а если придет другой человек — он и потерять их может.
Это хорошая идея, тем более, что у моих проектов и так есть их специфический каталог etc с настройками uwsgi, supervisor и др. Разве что я бы скорее использовал JSON вместо YAML.
После того как перешел на envdir, с болью вспоминаю разные файлы настроек для разных окружений local / staging / production.
Кстати, если в продакшене используется postgres и redis, крайне желательно, чтобы при локальной разработке было все тоже самое. Современные инструменты позволяют легко это сделать.
The way you structure your envdir is left to you

Мне как-то проще структурировать саму конфигурацию, чем привлекать дополнительную сущность и её структурировать.

А насчёт PG/Redis в дев. среде согласен, у меня установлено на десктопе всё, что используется в продакшне. Но я всё-таки держу в голове ситуацию, когда проект надо запустить на другой машине по-быстрому, с минимумом зависимостей.
оберните проект в Vagrant и исчезнет боль с разными дев-окружениями
для staging/production использую отдельный репозиторий с ansible ролями и плейбуками, это упрощает деплой и хранение приватных настроек
для settings использую похожую схему как у вас, только везде явно указывается какой файл настроек надо использовать(нет неявного импорта local_settings.py)
Был миллион подобных статей, на habrahabr в том числе, и ваш вариант далеко не самый оптимальный.
Например, я использую production.py и development.py в каталоге settings.
В local.py хранятся пароли для базы данных и т.п.

в manage.py прописано использование settings.development, в wsgi.py — settings.production. Поэтому не нужно на production включать/выключать DEBUG.

Хотя даже здесь в комментариях описали как можно зайти еще дальше, и я собственно в разных проектах использую разные подходы (по желанию или необходимости, например, в проектах под buildout одна структура настроек, под virtualenv — другая).
У меня настройки сделаны классами с помощью django-configuraions(ну люблю я когда один файлик settings.py а не куча всяких файлов с настройкми).
Все настройки через переменные окружения(использую свой django-confy)
В uwsgi у меня отдельные секции для development и production. например:

`
[uwsgi]
; тут общие настройки
; и потом идут секции с настройками кэширования, статистики, спулера и разные другие

[production]
env = DEBUG=False
env = DJANGO_CONFIGURATION=Production
ini = :uwsgi
ini = :cache
ini = :stats
ini = :spools
disable-logging
ignore-write-errors
ignore-sigpipe
print = Loaded production settings!

[development]
logto = %dlogs/%c.uwsgi.log
env = DEBUG=True
env = DJANGO_CONFIGURATION=Development
venv = /server/.py/%c
ini = :uwsgi
ini = :cache
ini = :spools
ini = :staticfiles
py-autoreload = 2
show-config
print = Loaded development settings!
`

То есть из uwsgi передается параметр в каком режиме загружать проект.
Запускаю как-то так(содержимое Procfile):

web: newrelic-admin run-program uwsgi --ini uwsgi.ini:production
Если есть что-то такое, что мне нужно быстро включить или выключить, я это тоже делаю через переменные окружения. Наример

if env('OPBEAT'):
    INSTALLED_APPS += ['opbeat.contrib.django',]
    MIDDLEWARE_CLASSES += [
        'opbeat.contrib.django.middleware.OpbeatAPMMiddleware',
    ]
    OPBEAT = {
        'ORGANIZATION_ID': env('OPBEAT_ORGANIZATION_ID'),
        'APP_ID': env('OPBEAT_APP_ID'),
        'SECRET_TOKEN': env('OPBEAT_SECRET_TOKEN'),
    }

if env('RAVEN'):
    INSTALLED_APPS += ['raven.contrib.django.raven_compat',]
    MIDDLEWARE_CLASSES += [
        'raven.contrib.django.middleware.Sentry404CatchMiddleware',
        'raven.contrib.django.middleware.SentryResponseErrorIdMiddleware',
    ]
    RAVEN_CONFIG = {
        'dsn': env('SENTRY_DSN'),
        # 'release': raven.fetch_git_sha(root),
    }
Ну, вообще-то, использовать переменные окружения для передачи паролей и секретных параметров — не очень секьюрно.

Любой сторонний процесс из-под другого пользователя может проявить любопытство:

cat /proc/<pid>/environ

Я не совсем понимаю кто поставил минус за идею хранить все в отдельном файле с урезанными правами, возможно у него есть аргументы против.
UFO just landed and posted this here
Sign up to leave a comment.

Articles