Як керувати налаштуваннями місцевих та виробничих в Django?


298

Який рекомендований спосіб керування налаштуваннями для місцевого розвитку та виробничого сервера? Деякі з них (як константи тощо) можуть бути змінені / доступні в обох, але деякі з них (наприклад, шляхи до статичних файлів) повинні залишатися різними, а отже, не слід перезаписувати кожного разу, коли новий код розгортається.

Наразі я додаю всі константи до settings.py. Але кожен раз, коли я змінюю константу локально, я повинен копіювати її на сервер виробництва та редагувати файл для конкретних змін виробництва: :(

Правка: схоже, що немає стандартної відповіді на це питання, я прийняв найпопулярніший метод.



Погляньте, будь ласка, на конфігурації джанго .
JJD

2
Прийнятий метод вже не є найпопулярнішим.
Даніель

2
django-split-settings дуже простий у використанні. Тут не потрібно перезаписувати будь-які налаштування за замовчуванням.
sobolevn

Вам слід використовувати файл base.py та у вашому local.py "з. імпорту бази *", такий самий у вашому production.py "з. імпорту бази *", вам потрібно запустити свій проект із: python management.py runserver - settings = project_name.settings.local
Роберт Соліс

Відповіді:


127

В settings.py:

try:
    from local_settings import *
except ImportError as e:
    pass

Ви можете перекрити те, що потрібно local_settings.py; тоді він повинен залишатися поза вашим контролем версій. Але оскільки ви згадуєте про копіювання, я гадаю, що ви не використовуєте жодного;)


3
Щоб полегшити відстеження / розгортання нових налаштувань, використовуйте "local_settings.py" на машинах виробництва / тестування, а жодних - на розробці.
Джон Мей

8
Так я і роблю - додаю ці рядки в кінці settings.py, щоб вони могли замінити налаштування за замовчуванням
даонб

61
Такий підхід означає, що у вас є неперевершений код, який працює в розробці та виробництві. І кожен розробник має різну базу коду. Я називаю анти-шаблон тут.
pydanny

8
@pydanny Проблема полягає в тому, що Django зберігає її конфігурацію у файлі .py. Ви не можете розраховувати, що всі розробники та сервер виробництва використовуватимуть однакові налаштування, тому вам потрібно змінити цей .py файл або реалізувати якесь альтернативне рішення (.ini файли, середовище тощо).
Tupteq

3
Я вважаю за краще викликати модуль, settings_localа не local_settingsгрупувати його settings.pyв алфавітному списку папок. Не слід settings_local.pyконтролювати версії, використовуючи .gitignoreяк облікові дані, не належать до Git. Уявіть, що їх відкрито шукати випадково. Я зберігаю в git файл шаблону, який називається settings_local.py.txtзамість цього.
перерва лінії

297

Дві совки Django: Кращі практики для Django 1.5 пропонують використовувати контроль версій для файлів налаштувань та зберігати файли в окремому каталозі:

project/
    app1/
    app2/
    project/
        __init__.py
        settings/
            __init__.py
            base.py
            local.py
            production.py
    manage.py

base.pyФайл містить загальні налаштування (такі як MEDIA_ROOT або ADMIN), в той час як local.pyі production.pyє налаштування сайту специфічні:

У базовому файлі settings/base.py:

INSTALLED_APPS = (
    # common apps...
)

У файлі налаштувань локальної розробки settings/local.py:

from project.settings.base import *

DEBUG = True
INSTALLED_APPS += (
    'debug_toolbar', # and other apps for local development
)

У файлі налаштувань створення файлу settings/production.py:

from project.settings.base import *

DEBUG = False
INSTALLED_APPS += (
    # other apps for production site
)

Потім, коли ви запускаєте django, ви додаєте --settingsпараметр:

# Running django for local development
$ ./manage.py runserver 0:8000 --settings=project.settings.local

# Running django shell on the production site
$ ./manage.py shell --settings=project.settings.production

Автори книги також розмістили зразок шаблону макета проекту на Github.


62
Зауважте, що замість --settingsкожного разу ви можете встановити DJANGO_SETTINGS_MODULEenvvar. Це чудово працює, наприклад, з Heroku: встановіть його у глобальному масштабі на виробництво, а потім замініть його на dev у вашому .env-файлі.
Саймон Вебер

9
Використання DJANGO_SETTINGS_MODULEenv var - найкраща ідея тут, дякую Саймону.
кібібу

20
Можливо, вам потрібно буде змінити BASE_DIRналаштування наos.path.dirname(os.path.realpath(os.path.dirname(__file__) + "/.."))
Петр Пеллер

5
@rsp згідно з документами django, ви імпортуєте from django.conf import settingsоб'єкт, який абстрагує інтерфейс і від'єднує код від місця налаштувань, docs.djangoproject.com/en/dev/topics/settings/…

3
Якщо я встановив DJANGO_SETTINGS_MODULE через змінну середовища, чи все-таки мені потрібен os.environ.setdefault ("DJANGO_SETTINGS_MODULE", "projectname.settings.production") у моєму файлі wsgi.py? Крім того, я встановив екологічний var за допомогою: export DJANGO_SETTINGS_MODULE = projectname.settings.local, але він втрачається, коли я закриваю термінал. Що я можу зробити, щоб її зберегти? Чи слід додати цей рядок до файлу bashrc?
Криц

71

Замість цього settings.pyвикористовуйте цей макет:

.
└── settings/
    ├── __init__.py  <= not versioned
    ├── common.py
    ├── dev.py
    └── prod.py

common.py це місце, де живе більшість вашої конфігурації.

prod.py імпортує все із загального і переосмислює все, що потрібно, щоб перекрити:

from __future__ import absolute_import # optional, but I like it
from .common import *

# Production overrides
DEBUG = False
#...

Аналогічно dev.pyімпортує все з common.pyі переосмислює все, що потрібно, щоб перекрити.

Нарешті, __init__.pyце місце, де ви визначаєте, які параметри потрібно завантажити, а також там, де ви зберігаєте секрети (тому цей файл не повинен бути розроблений):

from __future__ import absolute_import
from .prod import *  # or .dev if you want dev

##### DJANGO SECRETS
SECRET_KEY = '(3gd6shenud@&57...'
DATABASES['default']['PASSWORD'] = 'f9kGH...'

##### OTHER SECRETS
AWS_SECRET_ACCESS_KEY = "h50fH..."

Що мені подобається у цьому рішенні:

  1. Все є у вашій системі версій, крім секретів
  2. Більшість налаштувань знаходиться в одному місці: common.py.
  3. Прод-специфічні речі входять prod.py, специфічні для Dev речі dev.py. Це просто.
  4. Ви можете перевизначити матеріал з common.pyв prod.pyабо dev.py, і ви можете змінити що - небудь в __init__.py.
  5. Це прямий пітон. Жодних повторних імпортів хаків.

2
Я все ще намагаюся розібратися, що потрібно встановити в проекті.wsgi та файли management.py для файлу налаштувань. Ви пролиєте на це трохи світла? Зокрема, у файлі Manag.py у мене є os.environ.setdefault("DJANGO_SETTINGS_MODULE", "foobar.settings")foobar - це папка з __init__.pyфайлом, а параметри - це папка з __init__.pyфайлом, яка містить мої секрети та імпортує dev.py, який потім імпортує common.py. EDIT Nevermind, у мене не був встановлений необхідний модуль. Моє ліжко! Це чудово працює !!
teewuane

5
Дві речі: 1) краще встановити Debug = True у своєму dev.py, ніж = False у вашому prod.py. 2) Замість того, щоб увімкнути init .py, переключіться за допомогою середовища середовища DJANGO_SETTINGS_MODULE. Це допоможе при розгортанні PAAS (наприклад, Heroku).
Роб Грант

Коли я використовую цю установку в django 1.8.4 і намагаюся runserver, я отримую "django.core.exceptions.ImproperlyConfigured: Налаштування SECRET_KEY не повинно бути порожнім". Навіть у мене є SECRET_KEY у моєму файлі init .py. Я щось пропускаю?
polarcare

Хіба використання безпечного використання чогось типу AWS_SECRET_ACCESS_KEY = os.getenv ("AWS_SECRET_ACCESS_KEY") ? Чесне запитання - я знаю, чому ви не хочете, щоб його розглядали, але інша альтернатива - це отримати його з оточення. Хто, звичайно, задає питання про встановлення змінної середовища, але це може бути залишено у вашому механізмі розгортання, ні?
JL Peyret

20

Я використовую трохи модифіковану версію налаштувань стилю "if DEBUG", які розмістив Harper Shelby. Очевидно, що залежно від середовища (win / linux / тощо) код може знадобитися трохи підправити.

Раніше я використовував "if DEBUG", але виявив, що періодично мені потрібно робити тестування з DEUBG, встановленим на False. Що я дійсно хотів виділити, якщо середовище була виробництвом чи розвитком, що дало мені свободу вибору рівня DEBUG.

PRODUCTION_SERVERS = ['WEBSERVER1','WEBSERVER2',]
if os.environ['COMPUTERNAME'] in PRODUCTION_SERVERS:
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION
TEMPLATE_DEBUG = DEBUG

# ...

if PRODUCTION:
    DATABASE_HOST = '192.168.1.1'
else:
    DATABASE_HOST = 'localhost'

Я б ще вважав цей спосіб налаштування незавершеним. Я не бачив жодного способу обробки налаштувань Django, який би охоплював усі основи, і в той же час не був загальним клопотом з налаштуванням (я не збиваюся з методів файлів налаштувань 5x).


Це та річ, яку дозволяє фактичне налаштування Джанго - фактичний файл коду, і я на це натякав. Я нічого подібного не робив, але, безумовно, таке рішення може бути кращою загальною відповіддю, ніж моя.
Харпер Шелбі,

3
Я просто вперше зіткнувся з цим і вирішив (успішно!) Використовувати ваше рішення, з невеликою різницею: я використовував uuid.getnode (), щоб знайти uuid моєї системи. Тому я тестую, чи використовував uuid.getnode () == 12345678901 (фактично інше число) замість використовуваного тесту os.environ. Не вдалося знайти документацію, щоб переконати мене в тому, що os.environ ['COMPUTERNAME'] унікальний на комп'ютер.
Джо Голтон

os.environ ['COMPUTERNAME'] не працює на Amazon AWS Ubuntu. Я отримую KeyError.
nu everest

Під час використання UUID це рішення виявилося для мене найкращим та найпростішим. Для цього не потрібно багато складних і надмодульованих печворків. У виробничому середовищі вам все одно потрібно помістити паролі бази даних та SECRET_KEY в окремий файл, який знаходиться поза контролем версій.
nu everest

os.environ['COMPUTERNAME']на жаль, не працює на PythonAnywhere. Ви отримуєте KeyError.
nbeuchat

14

Я використовую settings_local.py та settings_production.py. Спробувавши кілька варіантів, я виявив, що просто витрачати час на складні рішення, коли просто мати два файли налаштувань легко і швидко.

Коли ви використовуєте mod_python / mod_wsgi для свого проекту Django, вам потрібно вказати його на файл налаштувань. Якщо ви вказали це на app / settings_local.py на локальному сервері та app / settings_production.py на виробничому сервері, тоді життя стає легким. Просто відредагуйте відповідний файл налаштувань та перезапустіть сервер (сервер розробки Django автоматично перезапуститься).


2
А як щодо локального сервера розвитку? чи є спосіб сказати веб-серверу django (запустити за допомогою python manage.py runserver), який файл налаштувань використовувати?
akv

2
@akv, якщо до кінця команди runserver додати --settings = [ім'я модуля] (немає .py розширення), ви можете вказати, який файл налаштувань використовувати. Якщо ви збираєтеся це зробити, зробіть собі послугу і зробіть скрипт / пакетний файл оболонки з налаштованими налаштуваннями розробки. Повірте мені, ваші пальці будуть вам вдячні.
Т. Стоун

це рішення, яке я використовую. злом файлу налаштувань, який використовуватиметься як для виробництва, так і для розробки, є безладним
Джордж Годик,

4
Я думаю, що краще використовувати settings.py в розробці, оскільки вам не доведеться постійно вказувати це.
Андре Боссар

Чи правильно я вважаю, що цей метод вимагає імпорту модуля налаштувань через проксі, django.conf.settings? Інакше вам потрібно буде відредагувати декларації про імпорт, щоб вказати на файл правильних налаштувань під час натискання наживо.
Groady

8

TL; DR: фокус полягає в тому, щоб змінити їх, os.environmentперш ніж імпортувати settings/base.pyбудь-який settings/<purpose>.py, це значно спростить речі.


Думка про всі ці файли, що переплітаються, болить у мене. Поєднання, імпорт (іноді умовно), переопределення, виправлення того, що вже було встановлено у випадку, якщо DEBUGналаштування змінилися згодом. Який кошмар!

Через роки я перебирав усі різні рішення. Всі вони дещо працюють, але так боляче керувати. WTF! Чи нам справді потрібні всі ці клопоти? Ми почали лише з одного settings.pyфайлу. Тепер нам потрібна документація, щоб правильно поєднати все це в правильному порядку!

Я сподіваюся, що я нарешті потрапив на (моє) солодке місце з рішенням нижче.

Давайте підкажемо цілі (деякі загальні, якісь мої)

  1. Зберігайте секрети в секреті - не зберігайте їх у репо!

  2. Встановлення / читання ключів та секретів за допомогою параметрів середовища, 12 факторного стилю .

  3. Мати обгрунтовані параметри за замовчуванням. Ідеально для місцевого розвитку вам більше за замовчуванням не потрібно нічого.

  4. … Але намагайтеся зберегти виробництво за замовчуванням у безпеці. Краще пропустити налаштування, що перевизначає локально, ніж пам'ятати, щоб налаштувати параметри за замовчуванням, безпечні для виробництва.

  5. Мати можливість вмикати DEBUG/ вимикати таким чином, що може впливати на інші налаштування (наприклад, за допомогою стисненого JavaScript чи ні).

  6. Перемикання між цільовими налаштуваннями, як-от локальне / тестування / постановка / виробництво, повинно базуватися лише на DJANGO_SETTINGS_MODULE, не більше.

  7. … Але дозволити подальшу параметризацію за допомогою таких параметрів середовища DATABASE_URL.

  8. … Також дозволити їм використовувати різні налаштування цілей та запускати їх локально поруч, наприклад. налаштування виробництва на локальній машині розробника, щоб отримати доступ до виробничої бази даних або аркушів стильового стилю для тестування диму.

  9. Збій, якщо змінна середовища не встановлена ​​явно (вимагає мінімум порожнього значення), особливо у виробництві, наприклад. EMAIL_HOST_PASSWORD.

  10. Відповідь до DJANGO_SETTINGS_MODULEвстановленого за замовчуванням в Manag.py під час запуску проекту django-admin

  11. Тримайте умовні до мінімуму, якщо умова визначили тип середовища (наприклад, для файлу журналу виробництва набору та цьогообертання), настройки перевизначення відповідного файлу замислили настройки.

Не роби

  1. Не дозволяйте django прочитати налаштування DJANGO_SETTINGS_MODULE з файлу.
    Тьфу! Подумайте, як це мета. Якщо вам потрібен файл (наприклад, docker env), прочитайте це в середовищі, перш ніж заглядати в процес django.

  2. Не змінюйте DJANGO_SETTINGS_MODULE у своєму проекті / коді програми, наприклад. на основі імені хоста або імені процесу
    Якщо вам лінь встановити змінну середовища (як для setup.py test), зробіть це в інструментах безпосередньо перед запуском коду проекту.

  3. Уникайте магії та виправлення того, як django читає його налаштування, попередньо обробляйте налаштування, але не заважайте потім.

  4. Немає складної логіки, заснованої на логіці. Конфігурація має бути виправлена ​​та матеріалізована, а не обчислюватися під час руху. Надання за замовчуванням просто достатньо логіки тут.
    Ви дійсно хочете налагоджувати, чому локально у вас правильний набір налаштувань, але у виробництві на віддаленому сервері, на одній із сотень машин щось обчислюється по-іншому? Ой! Одиничні тести? Для налаштувань? Серйозно?

Рішення

Моя стратегія складається з чудової Джанго-окружа використовується з iniфайлами стилів, забезпечуючи по os.environmentзамовчуванням для місцевого розвитку, деякі мінімальні і короткі settings/<purpose>.pyфайли , які мають import settings/base.py ПІСЛЯos.environment був створений зINI файлу. Це ефективно дає нам ін'єкцію налаштувань.

Хитрість тут полягає в тому, щоб змінити їх os.environmentперед імпортомsettings/base.py .

Щоб побачити повний приклад, перейдіть на репо: https://github.com/wooyek/django-settings-strategy

.
   manage.py
├───data
└───website
    ├───settings
          __init__.py   <-- imports local for compatibility
          base.py       <-- almost all the settings, reads from proces environment 
          local.py      <-- a few modifications for local development
          production.py <-- ideally is empty and everything is in base 
          testing.py    <-- mimics production with a reasonable exeptions
          .env          <-- for local use, not kept in repo
       __init__.py
       urls.py
       wsgi.py

налаштування / .env

За замовчуванням для місцевого розвитку. Таємний файл, в основному встановлює необхідні змінні середовища. Встановіть їх у порожні значення, якщо вони не потрібні для місцевого розвитку. Ми надаємо за замовчуванням тут, а не вsettings/base.py можемо вийти з ладу на будь-якій іншій машині, якщо вона відсутня в оточенні.

налаштування / local.py

Тут відбувається завантаження середовища settings/.env, а потім імпорт загальних налаштувань settings/base.py. Після цього ми можемо змінити декілька, щоб полегшити місцевий розвиток.

import logging
import environ

logging.debug("Settings loading: %s" % __file__)

# This will read missing environment variables from a file
# We wan to do this before loading a base settings as they may depend on environment
environ.Env.read_env(DEBUG='True')

from .base import *

ALLOWED_HOSTS += [
    '127.0.0.1',
    'localhost',
    '.example.com',
    'vagrant',
    ]

# https://docs.djangoproject.com/en/1.6/topics/email/#console-backend
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'

LOGGING['handlers']['mail_admins']['email_backend'] = 'django.core.mail.backends.dummy.EmailBackend'

# Sync task testing
# http://docs.celeryproject.org/en/2.5/configuration.html?highlight=celery_always_eager#celery-always-eager

CELERY_ALWAYS_EAGER = True
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True

налаштування / production.py

Для виробництва ми не повинні очікувати файлу оточення, але його легше мати, якщо ми щось тестуємо. Але в будь-якому випадку, щоб уникнути вбудованих кількох значень за замовчуванням, тому settings/base.pyможна відповісти відповідним чином.

environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
from .base import *

Головні моменти, які тут цікавляться, є DEBUGі ASSETS_DEBUGпереосмислення, вони будуть застосовані до пітонаos.environ ТОЛЬКО, якщо вони МІССУЮТЬ із середовища та файлу.

Це будуть наші виробничі настройки за замовчуванням, не потрібно розміщувати їх у середовищі чи файлах, але вони можуть бути скасовані за потреби. Акуратно!

налаштування / base.py

Це ваші в основному налаштування джанго ванілі, з кількома умовами та читанням їх з оточення. Практично все є тут, підтримуючи всі цільові середовища послідовними та максимально схожими.

Основні відмінності наведені нижче (я сподіваюся, що вони пояснюють себе):

import environ

# https://github.com/joke2k/django-environ
env = environ.Env()

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Where BASE_DIR is a django source root, ROOT_DIR is a whole project root
# It may differ BASE_DIR for eg. when your django project code is in `src` folder
# This may help to separate python modules and *django apps* from other stuff
# like documentation, fixtures, docker settings
ROOT_DIR = BASE_DIR

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG', default=False)

INTERNAL_IPS = [
    '127.0.0.1',
]

ALLOWED_HOSTS = []

if 'ALLOWED_HOSTS' in os.environ:
    hosts = os.environ['ALLOWED_HOSTS'].split(" ")
    BASE_URL = "https://" + hosts[0]
    for host in hosts:
        host = host.strip()
        if host:
            ALLOWED_HOSTS.append(host)

SECURE_SSL_REDIRECT = env.bool('SECURE_SSL_REDIRECT', default=False)

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

if "DATABASE_URL" in os.environ:  # pragma: no cover
    # Enable database config through environment
    DATABASES = {
        # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
        'default': env.db(),
    }

    # Make sure we use have all settings we need
    # DATABASES['default']['ENGINE'] = 'django.contrib.gis.db.backends.postgis'
    DATABASES['default']['TEST'] = {'NAME': os.environ.get("DATABASE_TEST_NAME", None)}
    DATABASES['default']['OPTIONS'] = {
        'options': '-c search_path=gis,public,pg_catalog',
        'sslmode': 'require',
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            # 'ENGINE': 'django.contrib.gis.db.backends.spatialite',
            'NAME': os.path.join(ROOT_DIR, 'data', 'db.dev.sqlite3'),
            'TEST': {
                'NAME': os.path.join(ROOT_DIR, 'data', 'db.test.sqlite3'),
            }
        }
    }

STATIC_ROOT = os.path.join(ROOT_DIR, 'static')

# django-assets
# http://django-assets.readthedocs.org/en/latest/settings.html

ASSETS_LOAD_PATH = STATIC_ROOT
ASSETS_ROOT = os.path.join(ROOT_DIR, 'assets', "compressed")
ASSETS_DEBUG = env('ASSETS_DEBUG', default=DEBUG)  # Disable when testing compressed file in DEBUG mode
if ASSETS_DEBUG:
    ASSETS_URL = STATIC_URL
    ASSETS_MANIFEST = "json:{}".format(os.path.join(ASSETS_ROOT, "manifest.json"))
else:
    ASSETS_URL = STATIC_URL + "assets/compressed/"
    ASSETS_MANIFEST = "json:{}".format(os.path.join(STATIC_ROOT, 'assets', "compressed", "manifest.json"))
ASSETS_AUTO_BUILD = ASSETS_DEBUG
ASSETS_MODULES = ('website.assets',)

Останній біт показує тут потужність. ASSETS_DEBUGмає розумний дефолт, який можна змінитиsettings/production.py і навіть той, який може бути замінений налаштуваннями середовища! Так!

По суті, ми маємо змішану ієрархію важливості:

  1. settings / .py - встановлює параметри за замовчуванням залежно від призначення, не зберігає секрети
  2. settings / base.py - здебільшого контролюється середовищем
  3. налаштування навколишнього середовища - дитина з 12 факторами!
  4. settings / .env - локальні параметри за замовчуванням для легкого запуску

Привіт, Януш ... так у файлі .env ходитимуть усі ключі API та ключі auth та паролі тощо? Так само, як TWILLIO_API = "abc123"? Або TWILLIO_API = env ("TWILLIO_API")?
dbinott

Так, але це лише резервний варіант для налаштувань середовища. Цей файл стане в нагоді для розробки, але не зберігається під час репо або не висувається у виробництво, де слід суворо використовувати налаштування навколишнього середовища або еквівалент вашої платформи, що, у свою чергу, встановить налаштування середовища для серверного процесу.
Януш Сконієчний

7

Я керую своїми конфігураціями за допомогою налаштувань django-split-split .

Це заміна, що випадає для налаштування за замовчуванням. Це просто, але конфігурується. І рефакторинг ваших налаштувань exisitng не потрібно.

Ось невеликий приклад (файл example/settings/__init__.py):

from split_settings.tools import optional, include
import os

if os.environ['DJANGO_SETTINGS_MODULE'] == 'example.settings':
    include(
        'components/default.py',
        'components/database.py',
        # This file may be missing:
        optional('local_settings.py'),

        scope=globals()
    )

Це воно.

Оновлення

Я написав повідомлення в блозі про керування djangoналаштуваннями за допомогою django-split-sttings. Подивитися!


1
Я спробував це .. один раз наткнувся на стіну, коли я спробував запустити тести блоку на джанго .. Я просто не міг придумати, як вказати, з якого файла налаштувань читати
abbood

Я створив для вас суть: gist.github.com/sobolevn/006c734f0520439a4b6c16891d65406c
sobolevn

я отримав - щось на зразок цього в моєму коді, тому я перевірити прапор settings.DEBUG знати , якщо я хочу імпортувати матеріал .. цей прапор завжди встановлюється в брехню в Джанго модульних тестів (див тут ) , так що моя робота навколо , щоб перевизначити їх в кожен тест так
аборт

Ось ще одне питання, однак: мій uwsgi.iniфайл має різні налаштування через dev / prod .. будь-яке уявлення про те, як змусити його вибирати значення з мого файлу налаштувань?
абат

Вибачте, я не отримую налаштування. Ви можете задати окреме запитання з більш детальною інформацією, і я спробую вам допомогти.
sobolevn

6

Проблема більшості цих рішень полягає в тому, що ви або застосували свої локальні налаштування перед загальними, або після них.

Тому неможливо перекрити такі речі

  • специфічні для env налаштування визначають адреси для пулу, що запам'ятовується, і у файлі основних параметрів це значення використовується для налаштування бекенда кешу
  • налаштування для ENV додають або видаляють програми / проміжне програмне забезпечення до стандартних

в той самий час.

Одне рішення може бути реалізовано за допомогою конфігураційних файлів "ini" у класі ConfigParser. Він підтримує декілька файлів, ледачу інтерполяцію рядків, значення за замовчуванням та безліч інших смаколиків. Після завантаження декількох файлів можна завантажувати більше файлів, і їх значення замінять попередні, якщо такі є.

Ви завантажуєте один або кілька конфігураційних файлів, залежно від адреси машини, змінних оточення та навіть значень у раніше завантажені конфігураційні файли. Тоді ви просто використовуєте проаналізовані значення для заповнення налаштувань.

Одна з стратегій, яку я успішно використовувала, була:

  • Завантажте defaults.iniфайл за замовчуванням
  • Перевірте ім'я машини та завантажте всі файли, які відповідали переверненій FQDN, від найкоротшого до найдовшого збігу (так що я завантажив net.ini, то net.domain.ini, потім net.domain.webserver01.ini, кожен, можливо, переосмисливши значення попереднього). Цей обліковий запис також для машин розробників, щоб кожен міг створити свій бажаний драйвер бази даних тощо для локальної розробки
  • Перевірте, чи є оголошене "ім'я кластера", і в такому випадку завантажте cluster.cluster_name.ini, яке може визначати такі речі, як IP-адреси бази даних та кешу

Як приклад чогось ви можете досягти за допомогою цього, ви можете визначити значення "субдомен" per-env, яке потім використовується в налаштуваннях за замовчуванням (як hostname: %(subdomain).whatever.net ) для визначення всіх необхідних імен хостів та файлів cookie, якими потрібно працювати django.

Це як DRY, що я міг отримати, більшість (існуючих) файлів мали лише 3 або 4 налаштування. Крім цього, мені довелося керувати конфігурацією клієнта, тому існував додатковий набір файлів конфігурації (з такими речами, як імена бази даних, користувачі та паролі, призначений субдомен тощо), один або більше на кожного клієнта.

Можна масштабувати це на мінімальному або високому рівні, ви просто введете у файл конфігурації ключі, які ви хочете налаштувати на середовище, і, як тільки буде необхідність у новому конфігурації, введіть попереднє значення у конфігурацію за замовчуванням та замініть його де необхідно.

Ця система виявилася надійною і добре працює з контролем версій. Він застосовується протягом тривалого часу, керуючи двома окремими кластерами додатків (15 і більше окремих примірників сайту django на машині) з більш ніж 50 клієнтами, де кластери змінювали розмір та кількість членів залежно від настрою системного адміністратора. .


1
Чи є у вас приклад того, як ви завантажуєте налаштування з ini в налаштування Django?
kaleissin

Див. Docs.python.org/2/library/configparser.html . Ви можете завантажити аналізатор, config = ConfigParser.ConfigParser() потім прочитати свої файли config.read(array_of_filenames)та отримати значення config.get(section, option). Отже, спочатку ви завантажуєте свій конфігурацію, а потім використовуєте його для читання значень для налаштувань.
переписано

5

Я також працюю з Laravel і мені подобається реалізація там. Я намагався імітувати його і поєднуючи його з рішенням, запропонованим Т. Стоун (дивіться вище):

PRODUCTION_SERVERS = ['*.webfaction.com','*.whatever.com',]

def check_env():
    for item in PRODUCTION_SERVERS:
        match = re.match(r"(^." + item + "$)", socket.gethostname())
        if match:
            return True

if check_env():
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION

Можливо, щось подібне допоможе вам.


4

Пам'ятайте, що settings.py - це файл прямого коду. Якщо припустити, що у вас немає DEBUG на виробництві (що є найкращою практикою), ви можете зробити щось на кшталт:

if DEBUG:
    STATIC_PATH = /path/to/dev/files
else:
    STATIC_PATH = /path/to/production/files

Досить базовий, але теоретично ви могли б піднятися на будь-який рівень складності, виходячи із лише значення DEBUG - або будь-якої іншої перевірки змінної чи коду, яку ви хотіли використати.


4

Для більшості моїх проектів я використовую такий зразок:

  1. Створіть settings_base.py, де я зберігаю параметри, спільні для всіх середовищ
  2. Кожного разу, коли мені потрібно використовувати нове середовище з конкретними вимогами, я створюю новий файл налаштувань (наприклад, settings_local.py), який успадковує вміст settings_base.py і переосмислює / додає відповідні змінні налаштування ( from settings_base import *)

(Для запуску manage.py комп'ютера з використанням режиму файлу , який ви просто використовувати --settings варіант команди: manage.py <command> --settings=settings_you_wish_to_use.py)


3

Моє рішення цієї проблеми також є дещо поєднанням деяких рішень, про які вже було сказано:

  • Я зберігаю файл з назвою, local_settings.pyякий містить вміст USING_LOCAL = Trueу розробниках таUSING_LOCAL = False prod
  • В settings.py я імпортую цей файл, щоб отримати USING_LOCALналаштування

Потім я базую всі мої налаштування, що залежать від середовища:

DEBUG = USING_LOCAL
if USING_LOCAL:
    # dev database settings
else:
    # prod database settings

Я вважаю за краще мати два окремі файли settings.py, які мені потрібно підтримувати, оскільки я можу простіше налаштувати свої налаштування в один файл, ніж поширити їх по декількох файлах. Так, коли я оновлюю налаштування, я не забуваю робити це для обох середовищ.

Звичайно, у кожного методу є свої недоліки, і цей не є винятком. Проблема тут полягає в тому, що я не можу перезаписати local_settings.pyфайл кожного разу, коли я натискаю свої зміни на виробництво, тобто я не можу просто копіювати всі файли наосліп, але це те, з чим я можу жити.


3

Я використовую варіацію згаданих вище jpartogi, що мені здається трохи коротшим:

import platform
from django.core.management import execute_manager 

computername = platform.node()

try:
  settings = __import__(computername + '_settings')
except ImportError: 
  import sys
  sys.stderr.write("Error: Can't find the file '%r_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % (computername, __file__))
  sys.exit(1)

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

В основному на кожному комп’ютері (розробці чи виробництві) я маю відповідний файл hostname_settings.py, який динамічно завантажується.


3

Також є Параметри класу Django. Я особисто є великим шанувальником цього. Він побудований одним з найактивніших людей на IRC Django. Ви б використовували параметри середовища для встановлення речей.

http://django-classy-settings.readthedocs.io/en/latest/


3

1 - Створіть нову папку всередині програми та налаштуйте ім'я до неї.

2 - Тепер створіть у ньому новий __init__.pyфайл і всередині нього запишіть

from .base import *

try:
    from .local import *
except:
    pass

try:
    from .production import *
except:
    pass

3 - Створіть три нових файли у назві папки налаштувань local.pyі production.pyтаbase.py .

4 - Всередині base.pyскопіюйте весь вміст попередньої settings.pyпапки та перейменуйте її чимось іншим, скажімоold_settings.py .

5 - У base.py змініть шлях BASE_DIR, щоб вказати на новий шлях налаштування

Стара стежка-> BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Нова стежка -> BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Таким чином, проект проекту може бути структурований і може бути керованим серед виробництва та місцевого розвитку.


2

Для того, щоб використовувати різні settingsконфігурації в різних середовищах, створіть інший файл налаштувань. А в сценарії розгортання запустіть сервер за допомогою --settings=<my-settings.py>параметра, за допомогою якого ви можете використовувати різні налаштування в різних середовищах.

Переваги використання цього підходу :

  1. Ваші налаштування будуть модульними залежно від кожного середовища

  2. Ви можете імпортувати master_settings.pyбазову конфігурацію, що містить базову конфігурацію, environmnet_configuration.pyі замінити значення, які ви хочете змінити в цьому середовищі.

  3. Якщо у вас є величезна команда, у кожного розробника може бути своя особа, local_settings.pyяку вони можуть додати до сховища коду без будь-якого ризику змінити конфігурацію сервера. Ви можете додати ці локальні налаштування, .gitnoreякщо ви використовуєте git або .hginoreякщо ви Mercurial для контролю версій (або будь-який інший). Таким чином, локальні налаштування навіть не будуть частиною фактичної бази кодів, підтримуючи його чистотою.


2

У мене налаштування розділилися наступним чином

settings/
     |
     |- base.py
     |- dev.py
     |- prod.py  

У нас є 3 середовища

  • дев
  • інсценування
  • виробництво

Зараз очевидно, що постановка та виробництво повинні мати максимально можливе подібне середовище. Так ми збереглиprod.py за обох.

Але був випадок, коли мені довелося визначити запущений сервер - це виробничий сервер. @T. Відповідь Стоун допомогла мені написати перевірку наступним чином.

from socket import gethostname, gethostbyname  
PROD_HOSTS = ["webserver1", "webserver2"]

DEBUG = False
ALLOWED_HOSTS = [gethostname(), gethostbyname(gethostname()),]


if any(host in PROD_HOSTS for host in ALLOWED_HOSTS):
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True  

1

Я розмежував його в Manag.py і створив два окремі файли налаштувань: local_settings.py та prod_settings.py.

У Manag.py я перевіряю, чи є локальним сервером або виробничим сервером. Якщо це локальний сервер, він би завантажив local_settings.py, а це виробничий сервер, він би завантажував prod_settings.py. В основному це виглядає так:

#!/usr/bin/env python
import sys
import socket
from django.core.management import execute_manager 

ipaddress = socket.gethostbyname( socket.gethostname() )
if ipaddress == '127.0.0.1':
    try:
        import local_settings # Assumed to be in the same directory.
        settings = local_settings
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'local_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)
else:
    try:
        import prod_settings # Assumed to be in the same directory.
        settings = prod_settings    
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'prod_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file prod_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)

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

Мені здалося, що простіше розділити файл налаштувань на два окремі файли, а не робити велику кількість ifs всередині файлу налаштувань.


1

Як альтернатива зберегти інший файл, якщо ви хочете: Якщо ви використовуєте git або будь-який інший VCS для перенесення кодів з локального на сервер, ви можете додати файл налаштувань до .gitignore.

Це дозволить вам мати різний вміст в обох місцях без жодних проблем. Так на сервері ви можете налаштувати незалежну версію settings.py, а будь-які зміни, внесені на локальному рівні, відображаються на сервері та навпаки.

Крім того, він також видалить файл settings.py з github, велика помилка, яку я бачив, як роблять багато новачків.



0

Я думаю, що найкраще рішення пропонує @T. Стоун, але я не знаю, чому просто не використовувати прапор DEBUG у Django. Я пишу нижче код для свого веб-сайту:

if DEBUG:
    from .local_settings import *

Завжди прості рішення краще, ніж складні.


-2

Я знайшов відповіді тут дуже корисними. (Чи було вирішено це остаточно? Остання відповідь була рік тому.) Розглянувши всі перелічені підходи, я придумав рішення, яке не бачив тут.

Мої критерії:

  • Все повинно бути в контролі джерел. Мені не подобаються химерні шматочки, що лежать навколо.
  • В ідеалі зберігайте налаштування в одному файлі. Я забуваю речі, якщо не дивлюсь на них :)
  • Немає вручну змін для розгортання. Потрібно мати можливість перевірити / натиснути / розгорнути за допомогою однієї тканинної команди.
  • Уникайте витоку налаштувань розвитку у виробництво.
  • Дотримуйтесь максимально наближеного до "стандартного" (* кашлю *) макета Джанго.

Я думав, що перехід на головну машину має певний сенс, але потім зрозумів, що справжня проблема полягає в різних налаштуваннях для різних середовищ , і був момент ага. Я ставлю цей код наприкінці файлу settings.py:

try:
    os.environ['DJANGO_DEVELOPMENT_SERVER'] # throws error if unset
    DEBUG = True
    TEMPLATE_DEBUG = True
    # This is naive but possible. Could also redeclare full app set to control ordering. 
    # Note that it requires a list rather than the generated tuple.
    INSTALLED_APPS.extend([
        'debug_toolbar',
        'django_nose',
    ])
    # Production database settings, alternate static/media paths, etc...
except KeyError: 
    print 'DJANGO_DEVELOPMENT_SERVER environment var not set; using production settings'

Таким чином, додаток за замовчуванням налаштовує виробничі налаштування, а це означає, що ви явно "перебуваєте в списках" свого середовища розробки. Набагато безпечніше забути встановити змінну середовища на місцевому рівні, ніж якби це було навпаки, і ви забули встановити щось у виробництві і дозволити використовувати деякі налаштування розробників.

Під час локальної розробки або з оболонки, або в .bash_profile, або де завгодно:

$ export DJANGO_DEVELOPMENT_SERVER=yep

(Або якщо ви розробляєтесь у Windows, встановіть через Панель управління або як там називались ці дні ... Windows завжди робила це настільки незрозумілим, що ви могли встановлювати змінні середовища.)

При такому підході налаштування розробників знаходяться в одному (стандартному) місці і просто змінюють виробничі, де це потрібно. Будь-яке переслідування з налаштуваннями розробки повинно бути абсолютно безпечним для здійснення контролю над джерелами, не впливаючи на виробництво.


Краще просто підтримувати різні конфігураційні файли та вибирати за допомогою стандартної змінної DJango env DJANGO_SETTINGS_MODULE
Rob Grant
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.