Как управлять локальными и производственными настройками в Django?

Каков рекомендуемый способ обработки настроек для локальной разработки и производственного сервера? Некоторые из них (например, константы и т.д.) Могут быть изменены/доступны в обоих случаях, но некоторые из них (например, пути к статическим файлам) должны оставаться разными и, следовательно, не должны перезаписываться при каждом развертывании нового кода.

В настоящее время я добавляю все константы в settings.py. Но каждый раз, когда я меняю какую-то константу локально, я должен скопировать ее на рабочий сервер и отредактировать файл для производственных изменений...:(

Изменить: похоже, нет стандартного ответа на этот вопрос, я принял самый популярный метод.

Ответ 1

В settings.py:

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

Вы можете переопределить то, что необходимо в local_settings.py; тогда он должен оставаться вне контроля версий. Но поскольку вы упоминаете копирование, я предполагаю, что вы не используете никого;)

Ответ 2

Два сокета Django: Best Practices для 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.

Ответ 3

Вместо 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 = '([email protected]&57...'
DATABASES['default']['PASSWORD'] = 'f9kGH...'

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

Что мне нравится в этом решении:

  • Все в вашей системе управления версиями, за исключением секретов
  • Большая часть конфигурации находится в одном месте: common.py.
  • Прод-специфические вещи идут в prod.py, dev-specific вещи идут в dev.py. Это просто.
  • Вы можете переопределить материал из common.py в prod.py или dev.py, и вы можете переопределить что-либо в __init__.py.
  • Это простой питон. Нет повторного импорта хаков.

Ответ 4

Я использую слегка измененную версию настроек стиля "if DEBUG", которую опубликовал Харпер Шелби. Очевидно, что в зависимости от среды (win/linux/etc.), Возможно, потребуется немного изменить код.

Я был в прошлом, используя "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 настроек файлов).

Ответ 5

Я использую settings_local.py и settings_production.py. Попробовав несколько вариантов, я обнаружил, что легко тратить время на сложные решения, когда просто наличие двух файлов настроек легко и быстро.

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

Ответ 6

Я управляю своими конфигурациями с помощью django-split-settings.

Это замена для настроек по умолчанию. Это просто, но настраивается. И рефакторинг ваших настроек 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()
    )

Что это.

Update

Я написал сообщение об управлении настройками django с помощью django-split-sttings. Посмотрите!

Ответ 7

Проблема с большинством этих решений заключается в том, что вы либо применяете локальные настройки до обычных, либо после них.

Поэтому невозможно переопределить такие вещи, как

  • параметры, определенные в env, определяют адреса для пула memcached, а в файле основных настроек это значение используется для настройки бэкэна кэша
  • настройки, зависящие от env, добавляют или удаляют приложения/промежуточное ПО по умолчанию.

в то же время.

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

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

Одна из моих успешных стратегий:

  • Загрузите файл defaults.ini по умолчанию
  • Проверьте имя машины и загрузите все файлы, которые соответствуют восстановленному полному доменному имени, от самого короткого совпадения до самого длинного совпадения (поэтому я загрузил net.ini, затем net.domain.ini, затем net.domain.webserver01.ini, каждый из которых, возможно, переопределяет значения предыдущего). Эта учетная запись также для машин разработчиков, поэтому каждый может настроить свой предпочтительный драйвер базы данных и т.д. Для локальной разработки.
  • Проверьте, есть ли объявленное имя кластера, и в этом случае загрузите cluster.cluster_name.ini, который может определять такие вещи, как IP-адреса базы данных и кеширования.

В качестве примера чего вы можете достичь с помощью этого, вы можете определить значение "поддомена" для каждого env, которое затем используется в настройках по умолчанию (как hostname: %(subdomain).whatever.net), чтобы определить все необходимые имена хостов и файлы cookie django должен работать.

Это как СУХОЙ, я мог бы получить, у большинства (существующих) файлов было всего 3 или 4 параметра. Кроме того, мне пришлось управлять конфигурацией клиента, поэтому существовал дополнительный набор файлов конфигурации (с такими именами, как имена баз данных, пользователи и пароли, назначенный поддомен и т.д.), Один или несколько пользователей.

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

Эта система доказала свою надежность и хорошо работает с контролем версий. Он долгое время использовался для управления двумя отдельными кластерами приложений (15 или более отдельных экземпляров сайта django на машину) с более чем 50 клиентами, в которых кластеры меняли размер и члены в зависимости от настроения системного администратора..

Ответ 8

Я также работаю с 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

Возможно, что-то подобное поможет вам.

Ответ 9

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, заданное в manage.py во время начального проекта django-admin

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

Не

  1. Не позволяйте django читать настройки DJANGO_SETTINGS_MODULE из файла.
    Тьфу! Подумайте, как это мета. Если вам нужен файл (например, докер env) прочитайте это в среду, прежде чем запускать процесс django.

  2. Не переопределяйте DJANGO_SETTINGS_MODULE в коде вашего проекта/приложения, например. на основе имени хоста или имени процесса.
    Если вам лень устанавливать переменные среды (например, для setup.py test), сделайте это в инструментах непосредственно перед запуском кода проекта.

  3. Избегайте магии и исправлений того, как django считывает настройки, предварительно обрабатывайте настройки, но не вмешивайтесь впоследствии.

  4. Никакой сложной логики, основанной на чепухе. Конфигурация должна быть фиксированной и материализованной, а не вычисленной на лету. Предоставление запасных значений по умолчанию здесь достаточно логики.
    Вы действительно хотите отладить, почему локально у вас есть правильный набор настроек, но на производстве на удаленном сервере, на одной из ста машин что-то вычисляется по-другому? Ой! Модульные тесты? Для настроек? Шутки в сторону?

Решение

Моя стратегия состоит из превосходных django-environment, используемых с файлами стилей 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

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

Основные отличия приведены ниже (я надеюсь, они говорят сами за себя):

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 - локальные настройки по умолчанию для легкого запуска

Ответ 10

Помните, что settings.py - это файл в реальном времени. Предполагая, что у вас нет набора DEBUG для производства (что является лучшей практикой), вы можете сделать что-то вроде:

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

Довольно простой, но теоретически вы могли бы перейти на любой уровень сложности, основываясь только на ценности DEBUG, или любой другой переменной или проверки кода, которую вы хотели использовать.

Ответ 11

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

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

(Чтобы запустить файл manage.py с настраиваемым файлом настроек, вы просто используете команду команды настройки: manage.py <command> --settings=settings_you_wish_to_use.py)

Ответ 12

Мое решение этой проблемы также представляет собой сочетание некоторых решений, уже заявленных здесь:

  • Я сохраняю файл под названием local_settings.py, у которого есть контент USING_LOCAL = True в dev и 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 всякий раз, когда я ввожу свои изменения в производство, то есть я не могу просто скопировать все файлы вслепую, но это то, с чем я могу жить.

Ответ 13

Я использую вариацию упомянутого выше 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 causing an ImportError somehow.)\n" % (computername, __file__))
  sys.exit(1)

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

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

Ответ 14

Также есть настройки Django Classy. Я лично большой поклонник этого. Он был построен одним из самых активных людей в Django IRC. Вы должны использовать окружения vars, чтобы установить что-то.

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

Ответ 15

Чтобы использовать другую конфигурацию settings в другой среде, создайте другой файл настроек. И в своем развертывании script запустите сервер, используя параметр --settings=<my-settings.py>, через который вы можете использовать разные настройки в разных средах.

Преимущества использования этого подхода:

  • Ваши настройки будут модульными на основе каждой среды

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

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

Ответ 16

Я различаю его в файле manage.py и создаю два отдельных файла настроек: local_settings.py и prod_settings.py.

В файле manage.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 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 causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)

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

Мне было проще отделить файл настроек от двух отдельных файлов, вместо того чтобы делать много файлов ifs внутри файла настроек.

Ответ 17

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

Это позволит вам иметь различный контент в обоих местах без каких-либо проблем. SO на сервере вы можете настроить независимую версию settings.py, а любые изменения, сделанные на локальном, не отразятся на сервере и наоборот.

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

Ответ 18

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.p и переименуйте его, используя что-то другое, скажем old_settings.py

5 - В файле base.py измените путь BASE_DIR, чтобы он указывал на новый путь настройки

Старый path-> BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(файл))))

Новый путь → BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(файл))))

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

Ответ 19

У меня были настройки разделены следующим образом

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

У нас есть 3 среды

  • DEV
  • постановка
  • производство

Теперь очевидно, что постановка и производство должны иметь максимально возможную аналогичную среду. Поэтому мы сохранили 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  

Ответ 21

Я думаю, что лучшее решение предлагает @T. Камень, но я не знаю, почему просто не использовать флаг DEBUG в Django. Я пишу код ниже для моего сайта:

if DEBUG:
    from .local_settings import *

Всегда простые решения лучше сложных.

Ответ 22

Я нашел ответы здесь очень полезными. (Было ли это окончательно решено? Последний ответ был год назад.) Рассмотрев все перечисленные подходы, я придумал решение, которое я не видел здесь.

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

  • Все должно быть в контроле источника. Мне не нравятся болтливые кусочки.
  • В идеале сохраните настройки в одном файле. Я забываю что-то, если я не смотрю прямо на них:)
  • Никаких ручных изменений для развертывания. Должен иметь возможность тестировать/нажимать/развертывать с помощью одной команды ткани.
  • Избегайте утечки настроек разработки в производство.
  • Держитесь как можно ближе к "стандартным" (* cough *) раскладке Django, насколько это возможно.

Я думал, что включение хост-машины имело какой-то смысл, но затем выяснилось, что реальная проблема здесь - разные настройки для разных сред и имеет момент аха. Я поместил этот код в конец моего файла 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 всегда делала это настолько неясным, что вы могли устанавливать переменные среды.)

При таком подходе настройки dev находятся в одном (стандартном) месте и просто при необходимости заменяют производственные. Любые ошибки, связанные с настройками разработки, должны быть абсолютно безопасными для фиксации контроля источника без какого-либо влияния на производство.