Каков рекомендуемый способ обработки настроек для локальной разработки и производственного сервера? Некоторые из них (например, константы и т.д.) Могут быть изменены/доступны в обоих случаях, но некоторые из них (например, пути к статическим файлам) должны оставаться разными и, следовательно, не должны перезаписываться при каждом развертывании нового кода.
В настоящее время я добавляю все константы в settings.py
. Но каждый раз, когда я меняю какую-то константу локально, я должен скопировать ее на рабочий сервер и отредактировать файл для производственных изменений...:(
Изменить: похоже, нет стандартного ответа на этот вопрос, я принял самый популярный метод.
В settings.py
:
try:
from local_settings import *
except ImportError as e:
pass
Вы можете переопределить то, что необходимо в local_settings.py
; тогда он должен оставаться вне контроля версий. Но поскольку вы упоминаете копирование, я предполагаю, что вы не используете никого;)
Два сокета 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.
--settings
каждый раз, вы можете установить DJANGO_SETTINGS_MODULE
DJANGO_SETTINGS_MODULE. Это хорошо работает, например, с Heroku: установите его глобально на производство, затем переопределите его с помощью dev в вашем файле .env.
DJANGO_SETTINGS_MODULE
использование DJANGO_SETTINGS_MODULE
env var - лучшая идея.
Вместо 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..."
Что мне нравится в этом решении:
common.py
.prod.py
, dev-specific вещи идут в dev.py
. Это просто.common.py
в prod.py
или dev.py
, и вы можете переопределить что-либо в __init__.py
.os.environ.setdefault("DJANGO_SETTINGS_MODULE", "foobar.settings")
Foobar - это папка с файлом __init__.py
а настройки - это папка с файлом __init__.py
который содержит мой секреты и импорт dev.py, который затем импортирует common.py. Редактировать Nevermind, у меня не было установлен модуль, который был необходим. Виноват! Это прекрасно работает !!
Я использую слегка измененную версию настроек стиля "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 настроек файлов).
Я использую settings_local.py и settings_production.py. Попробовав несколько вариантов, я обнаружил, что легко тратить время на сложные решения, когда просто наличие двух файлов настроек легко и быстро.
Когда вы используете mod_python/mod_wsgi для своего проекта Django, вам нужно указать его в файл настроек. Если вы укажете его на app/settings_local.py на своем локальном сервере и app/settings_production.py на вашем производственном сервере, тогда жизнь станет легкой. Просто отредактируйте соответствующий файл настроек и перезапустите сервер (сервер разработки Django перезапустится автоматически).
python manage.py runserver
django (запустить с помощью python manage.py runserver
), какой файл настроек использовать?
Я управляю своими конфигурациями с помощью 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()
)
Что это.
Я написал сообщение об управлении настройками django
с помощью django-split-sttings
. Посмотрите!
Проблема с большинством этих решений заключается в том, что вы либо применяете локальные настройки до обычных, либо после них.
Поэтому невозможно переопределить такие вещи, как
в то же время.
Одно решение может быть реализовано с использованием конфигурационных файлов 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 клиентами, в которых кластеры меняли размер и члены в зависимости от настроения системного администратора..
config = ConfigParser.ConfigParser()
затем прочитать ваши файлы config.read(array_of_filenames)
и получить значения, используя config.get(section, option)
. Итак, сначала вы загружаете свою конфигурацию, а затем используете ее для считывания значений для настроек.
Я также работаю с 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
Возможно, что-то подобное поможет вам.
Помните, что settings.py - это файл в реальном времени. Предполагая, что у вас нет набора DEBUG для производства (что является лучшей практикой), вы можете сделать что-то вроде:
if DEBUG:
STATIC_PATH = /path/to/dev/files
else:
STATIC_PATH = /path/to/production/files
Довольно простой, но теоретически вы могли бы перейти на любой уровень сложности, основываясь только на ценности DEBUG, или любой другой переменной или проверки кода, которую вы хотели использовать.
Я использую вариацию упомянутого выше 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, который динамически загружается.
Для большинства моих проектов я использую следующий шаблон:
from settings_base import *
)(Чтобы запустить файл manage.py с настраиваемым файлом настроек, вы просто используете команду команды настройки: manage.py <command> --settings=settings_you_wish_to_use.py
)
Мое решение этой проблемы также представляет собой сочетание некоторых решений, уже заявленных здесь:
local_settings.py
, у которого есть контент USING_LOCAL = True
в dev и USING_LOCAL = False
в prodsettings.py
Я делаю импорт в этот файл, чтобы получить параметр USING_LOCAL
Затем я основываю все свои зависящие от среды настройки на этом:
DEBUG = USING_LOCAL
if USING_LOCAL:
# dev database settings
else:
# prod database settings
Я предпочитаю, чтобы у меня было два отдельных файла settings.py, которые мне нужно поддерживать, поскольку я могу сохранить свои настройки, структурированные в одном файле, проще, чем их распространение по нескольким файлам. Подобно этому, когда я обновляю параметр, я не забываю сделать это для обеих сред.
Конечно, у каждого метода есть свои недостатки, и это не исключение. Проблема здесь в том, что я не могу перезаписать файл local_settings.py
всякий раз, когда я ввожу свои изменения в производство, то есть я не могу просто скопировать все файлы вслепую, но это то, с чем я могу жить.
Также есть настройки Django Classy. Я лично большой поклонник этого. Он был построен одним из самых активных людей в Django IRC. Вы должны использовать окружения vars, чтобы установить что-то.
1 - Создайте новую папку внутри своих настроек приложения и имени.
2 - Теперь создайте в нем новый init.py файл и внутри него напишите
from .base import *
try:
из .local import *
except:
передача
try:
из .production import *
except:
передача
3 - Создайте три новых файла в папке с настройками local.py и production.py и base.py
4 - Внутри base.py скопируйте все содержимое предыдущей папки settings.p и переименуйте его с чем-то другим, скажем, old_settings.py
5 - В base.py измените путь BASE_DIR, чтобы указать на новый путь установки
Старый путь- > 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(файл)))
теперь таким образом проектный dir может быть структурирован и может управляться между производством и локальным развитием.
TL; DR: Фокус в том, чтобы изменить os.environment
, прежде чем импортировать settings/base.py
в любой settings/<purpose>.py
, это значительно упростит ситуацию.
Просто думать обо всех этих переплетающихся файлах дает мне головную боль.
Комбинирование, импорт (иногда условно), переопределение, исправление того, что уже было установлено в случае, если установка DEBUG
изменилась позже.
Какой кошмар!
В течение многих лет я прошел через все разные решения. Они все работают, но так больно управлять.
WTF! Неужели нам действительно нужны все эти хлопоты? Мы начали с одного файла settings.py
.
Теперь нам нужна документация, чтобы правильно объединить все это в правильном порядке!
Надеюсь, я наконец ударил (мое) сладкое пятно с помощью решения ниже.
Храните тайны в секрете - не храните их в репо.
Установите/прочитайте ключи и секреты через настройки среды, 12 факторный стиль.
Имеют разумные резервные умолчания. В идеале для локального развития вам больше не нужно ничего по умолчанию.
... но попытайтесь сохранить безопасность по умолчанию. Лучше пропустить настройку локально, чем необходимость запоминать настройки по умолчанию, безопасные для производства.
У вас есть возможность включать/отключать DEBUG
таким образом, который может влиять на другие настройки (например, с помощью сжатого javascript или нет).
Переключение между целевыми настройками, такими как local/testing/staging/production, должно основываться только на DJANGO_SETTINGS_MODULE
, не более того.
... но разрешить дальнейшую параметризацию с помощью настроек среды, таких как DATABASE_URL
.
... также позволяют использовать разные целевые настройки и запускать их локально бок о бок, например. установки на локальной машине разработчика, для доступа к производственной базе данных или smoke test сжатых таблиц стилей.
Сбой, если переменная среды явно не задана (требуется минимальное значение), особенно в производстве, например. EMAIL_HOST_PASSWORD
.
Отвечайте по умолчанию DJANGO_SETTINGS_MODULE
, установленному в manage.py во время django-admin startproject
Сохраняйте условные условия до минимума, если это заданный тип среды (например, для файла журнала производственного набора и его вращения), переопределите настройки в соответствующем файле настроек.
Не позволяйте django читать настройку DJANGO_SETTINGS_MODULE формы.
Тьфу! Подумайте, как это мета. Если вам нужен файл (например, докер
env) прочитал это в среде, прежде чем приступить к процессу джанго.
Не переопределяйте DJANGO_SETTINGS_MODULE в коде проекта/приложения, например. на основе имени хоста или имени процесса.
Если вы ленитесь, чтобы установить переменную среды (например, для setup.py test
), сделайте это в инструментах непосредственно перед запуском кода проекта.
Избегайте магии и исправления того, как django считывает его настройки, предварительно обрабатывает настройки, но не вмешивается впоследствии.
Отсутствие сложной логической абсурдности. Конфигурация должна быть фиксированной и материализованной, а не вычисляться "на лету". Предоставление резервных значений по умолчанию - достаточно логики здесь. Вы действительно хотите отлаживать, почему локально у вас есть правильный набор настроек, но в производстве на удаленном сервере, на одной из ста машин, что-то вычислялось по-другому? Ой! Единичные тесты? Для настроек? Шутки в сторону?
Моя стратегия состоит из превосходного django-environ, используемого с файлами стиля 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 compatybility
│ │ base.py <-- almost all the settings, reads from proces environment
│ │ local.py <-- a few modifications for local development
│ │ production.py <-- ideally is empy 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
По умолчанию для локальной разработки. Секретный файл, в основном устанавливающий требуемые переменные среды.
Установите их в пустые значения, если они не требуются в локальной разработке.
Мы предоставляем значения по умолчанию здесь, а не в settings/base.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
Для производства мы не должны ожидать файла окружения, но его проще иметь, если мы что-то тестируем.
Но, так или иначе, чтобы обеспечить небольшое количество значений по умолчанию, поэтому settings/base.py
может ответить соответствующим образом.
environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
from .base import *
Основной интерес представляет здесь DEBUG
и ASSETS_DEBUG
переопределяет,
они будут применяться к python os.environ
ТОЛЬКО, если они НЕИСПРАВНОСТЬ из среды и файла.
Это будут наши производственные дефолты, не нужно помещать их в среду или файл, но при необходимости они могут быть переопределены. Ухоженная!
Это ваши настройки ванильного 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
и даже тот, который может быть переопределен настройкой среды! Ура!
По сути, мы имеем смешанную иерархию важности:
Чтобы использовать другую конфигурацию settings
в другой среде, создайте другой файл настроек. И в своем развертывании script запустите сервер, используя параметр --settings=<my-settings.py>
, через который вы можете использовать разные настройки в разных средах.
Преимущества использования этого подхода:
Ваши настройки будут модульными на основе каждой среды
Вы можете импортировать master_settings.py
, содержащую базовую конфигурацию в environmnet_configuration.py
, и переопределить значения, которые вы хотите изменить в этой среде.
Если у вас огромная команда, у каждого разработчика может быть свой собственный local_settings.py
, который они могут добавить в репозиторий кода без какого-либо риска изменения конфигурации сервера. Вы можете добавить эти локальные настройки в .gitnore
, если вы используете git или .hginore
, если вы Mercurial для управления версиями (или любого другого). Таким образом, локальные настройки даже не будут частью фактической базы кода, сохраняющей ее чистоту.
В качестве альтернативы поддерживать другой файл, если вы: Если вы используете git или любой другой VCS для отправки кодов с локального сервера, то вы можете добавить файл настроек в .gitignore.
Это позволит вам иметь различный контент в обоих местах без каких-либо проблем. SO на сервере вы можете настроить независимую версию settings.py, а любые изменения, сделанные на локальном, не отразятся на сервере и наоборот.
Кроме того, он удалит файл settings.py из github, а также большую ошибку, которую я видел много новичков.
Я различаю его в файле 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 внутри файла настроек.
У меня были настройки разделены следующим образом
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
Я нашел ответы здесь очень полезными. (Было ли это окончательно решено? Последний ответ был год назад.) Рассмотрев все перечисленные подходы, я придумал решение, которое я не видел здесь.
Мои критерии:
Я думал, что включение хост-машины имело какой-то смысл, но затем выяснилось, что реальная проблема здесь - разные настройки для разных сред и имеет момент аха. Я поместил этот код в конец моего файла 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 находятся в одном (стандартном) месте и просто при необходимости заменяют производственные. Любые ошибки, связанные с настройками разработки, должны быть абсолютно безопасными для фиксации контроля источника без какого-либо влияния на производство.