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

Я разрабатываю базовое приложение. Теперь на этапе развертывания стало ясно, что мне нужны как локальные настройки, так и производственные настройки.

Было бы замечательно знать следующее:

  • Как лучше всего иметь дело с настройками разработки и производства.
  • Как сохранить приложения, такие как django-debug-toolbar, только в среде разработки.
  • Любые другие советы и рекомендации по настройке и развертыванию.

Ответ 1

DJANGO_SETTINGS_MODULE окружения DJANGO_SETTINGS_MODULE определяет, какой файл настроек будет загружать Django.

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

Вот как:

Как отмечено в документации Django:

Значение DJANGO_SETTINGS_MODULE должно быть в синтаксисе пути Python, например, mysite.settings. Обратите внимание, что модуль настроек должен находиться в пути поиска импорта Python.

Итак, предположим, что вы создали myapp/production_settings.py и myapp/test_settings.py в вашем исходном хранилище.

В этом случае вы соответственно установите DJANGO_SETTINGS_MODULE=myapp.production_settings чтобы использовать первый, и DJANGO_SETTINGS_MODULE=myapp.test_settings чтобы использовать последний.


С этого момента проблема сводится к установке переменной среды DJANGO_SETTINGS_MODULE.

Настройка DJANGO_SETTINGS_MODULE с использованием скрипта или оболочки

Затем вы можете использовать скрипт начальной загрузки или менеджер процессов для загрузки правильных настроек (путем настройки среды) или просто запустить его из своей оболочки перед запуском Django: export DJANGO_SETTINGS_MODULE=myapp.production_settings.

Настройка DJANGO_SETTINGS_MODULE с помощью диспетчера процессов

Если вы не любите писать сценарий начальной загрузки, который задает среду (и на то есть веские причины!), Я бы порекомендовал использовать менеджер процессов:


Наконец, обратите внимание, что вы можете использовать переменную PYTHONPATH для хранения настроек в совершенно другом месте (например, на рабочем сервере, сохраняя их в /etc/). Это позволяет отделить конфигурацию от файлов приложения. Вы можете или не можете этого хотеть, это зависит от того, как структурировано ваше приложение.

Ответ 2

Обычно у меня есть один файл настроек для каждой среды и файл общих настроек:

/myproject/
  settings.production.py
  settings.development.py
  shared_settings.py

Каждый из моих файлов окружения имеет:

try:
    from shared_settings import *
except ImportError:
    pass

Это позволяет мне переопределить общие настройки, если необходимо (добавив изменения ниже этой строфы).

Затем я выбираю, какие файлы настроек следует использовать, введя его в settings.py:

ln -s settings.development.py settings.py

Ответ 3

По умолчанию используйте производственные настройки, но создайте файл с именем settings_dev.py в той же папке, что и ваш файл settings.py. Добавьте туда переопределения, например DEBUG=True.

На компьютере, который будет использоваться для разработки, добавьте его в свой файл ~/.bashrc:

export DJANGO_DEVELOPMENT=true

В нижней части вашего settings.py файла добавьте следующее.

# Override production variables if DJANGO_DEVELOPMENT env variable is set
if os.environ.get('DJANGO_DEVELOPMENT') is not None:
    from settings_dev import * 

(Обратите внимание, что импортировать * следует вообще избегать в Python, но это уникальное обстоятельство)

По умолчанию производственные серверы не будут переопределять что-либо. Готово!

По сравнению с другими ответами, это проще, потому что он не требует обновления PYTHONPATH или установки DJANGO_SETTINGS_MODULE, который позволяет работать только с одним проектом django за раз.

Ответ 4

Создайте несколько файлов settings*.py, экстраполируя переменные, которые необходимо изменить для каждой среды. Затем в конце вашего основного файла settings.py:

try:
  from settings_dev import *
except ImportError:
  pass

Вы сохраняете отдельные файлы settings_* для каждого этапа.

В верхней части вашего файла settings_dev.py добавьте следующее:

import sys
globals().update(vars(sys.modules['settings']))

Чтобы импортировать переменные, которые необходимо изменить.

В этой записи wiki есть больше идей о том, как разделить ваши настройки.

Ответ 5

Я использую awesome django-configurations, и все настройки сохраняются в моем settings.py:

from configurations import Configuration

class Base(Configuration):
    # all the base settings here...
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    ...

class Develop(Base):
    # development settings here...
    DEBUG = True 
    ...

class Production(Base):
    # production settings here...
    DEBUG = False

Чтобы настроить проект Django, я просто выполнил docs.

Ответ 6

Вот подход, который мы используем:

  • модуль settings для разделения настроек на несколько файлов для удобства чтения;
  • файл .env.json для хранения учетных данных и параметров, которые мы хотим исключить из нашего git-репозитория или которые зависят от конкретной среды;
  • файл env.py для чтения файла .env.json

Учитывая следующую структуру:

...
.env.json           # the file containing all specific credentials and parameters
.gitignore          # the .gitignore file to exclude '.env.json'
project_name/       # project dir (the one which django-admin.py creates)
  accounts/         # project apps
    __init__.py
    ...
  ...
  env.py            # the file to load credentials
  settings/
    __init__.py     # main settings file
    database.py     # database conf
    storage.py      # storage conf
    ...
venv                # virtualenv
...

С .env.json вроде:

{
    "debug": false,
    "allowed_hosts": ["mydomain.com"],
    "django_secret_key": "my_very_long_secret_key",
    "db_password": "my_db_password",
    "db_name": "my_db_name",
    "db_user": "my_db_user",
    "db_host": "my_db_host",
}

И project_name/env.py:

<!-- language: lang-python -->
import json
import os


def get_credentials():
    env_file_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    with open(os.path.join(env_file_dir, '.env.json'), 'r') as f:
        creds = json.loads(f.read())
    return creds


credentials = get_credentials()

У нас могут быть следующие настройки:

<!-- language: lang-py -->
# project_name/settings/__init__.py
from project_name.env import credentials
from project_name.settings.database import *
from project_name.settings.storage import *
...

SECRET_KEY = credentials.get('django_secret_key')

DEBUG = credentials.get('debug')

ALLOWED_HOSTS = credentials.get('allowed_hosts', [])

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    ...
]

if DEBUG:
    INSTALLED_APPS += ['debug_toolbar']

...

# project_name/settings/database.py
from project_name.env import credentials

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': credentials.get('db_name', ''),
        'USER': credentials.get('db_user', ''),
        'HOST': credentials.get('db_host', ''),
        'PASSWORD': credentials.get('db_password', ''),
        'PORT': '5432',
    }
}

Преимущества этого решения:

  • пользовательские учетные данные и конфигурации для локальной разработки без изменения хранилища git;
  • Конфигурация конкретной среды, например, вы можете иметь три разных среды с тремя разными .env.json такими как dev, stagging и production;
  • учетные данные не находятся в хранилище

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

Ответ 7

построение ответа cs01:

если у вас возникли проблемы с переменной окружения, установите его значение в строку (например, я сделал DJANGO_DEVELOPMENT="true").

Я также изменил рабочий процесс cs01 следующим образом:

#settings.py
import os
if os.environ.get('DJANGO_DEVELOPMENT') is not None:
    from settings_dev import * 
else:
    from settings_production import *
#settings_dev.py
development settings go here
#settings_production.py
production settings go here

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

Примечание. В Python 3 для импортированных файлов необходимо добавить . (например, from .settings_dev import *)

Ответ 8

Я использую файловую структуру folloring:

project/
   ...
   settings/
   settings/common.py
   settings/local.py
   settings/prod.py
   settings/__init__.py -> local.py

So __init__.py - это ссылка (ln в unix или mklink в окнах) на local.py или может быть на prod.py, поэтому конфигурация все еще находится в модуле project.settings, является чистой и организованной, и если вы хотите для использования конкретной конфигурации вы можете использовать переменную окружения DJANGO_SETTINGS_MODULE to project.settings.prod, если вам нужно запустить команду для рабочей среды.

В файлах prod.py и local.py:

from .shared import *

DATABASE = {
    ...
}

а файл shared.py хранится как глобальный без конкретных конфигураций.

Ответ 9

Если вы хотите сохранить один файл настроек, а ваша операционная система разработки отличается от вашей операционной системы, вы можете поместить ее в нижнюю часть своих настроек .py:

from sys import platform
if platform == "linux" or platform == "linux2":
    # linux
    # some special setting here for when I'm on my prod server
elif platform == "darwin":
    # OS X
    # some special setting here for when I'm developing on my mac
elif platform == "win32":
    # Windows...
    # some special setting here for when I'm developing on my pc

Подробнее: Как проверить операционную систему на Python?

Ответ 10

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

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

env.py:

#!usr/bin/python

DJANGO_ENV = True
ALLOWED_HOSTS = ['127.0.0.1', 'dev.mywebsite.com']

.gitignore:

mywebsite/env.py

settings.py:

if os.path.exists(os.getcwd() + '/env.py'):
    #env.py is excluded using the .gitignore file - when moving to production we can automatically set debug mode to off:
    from env import *
else:
    DJANGO_ENV = False

DEBUG = DJANGO_ENV

Я просто считаю, что это работает и намного более изящно - с env.py легко увидеть наши локальные переменные окружения, и мы можем обрабатывать все это без нескольких файлов settings.py или подобных файлов. Эти методы позволяют использовать все виды переменных локальной среды, которые мы бы не хотели устанавливать на нашем производственном сервере. Используя .gitignore с помощью контроля версий, мы также полностью интегрируем все.

Ответ 11

Вот как я делаю это за 6 простых шагов:

  1. Создайте папку внутри директории вашего проекта и назовите ее settings.

    структура проекта:

    myproject/
           myapp1/
           myapp2/              
           myproject/
                  settings/
    
  2. Создайте четыре файла python внутри каталога settings а именно: init.py, base.py, dev.py и prod.py

    файлы настроек:

    setting/
         init.py
         base.py
         prod.py
         dev.py 
    
  3. Откройте init.py и заполните его следующим содержанием:

    init.py:

    from .base import *
    # you need to set "myproject = 'prod'" as an environment variable 
    # in your OS (on which your website is hosted)
    if os.environ['myproject'] == 'prod':                          
       from .prod import * 
    else:
       from .dev import *   
    
  4. Откройте base.py и заполните его всеми общими настройками (которые будут использоваться как в производстве, так и в разработке), например:

    base.py:

    import os
    ...
    INSTALLED_APPS = [...]
    MIDDLEWARE = [...]
    TEMPLATES = [{...}]
    ...
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
    MEDIA_ROOT = os.path.join(BASE_DIR, '/path/')
    MEDIA_URL = '/path/'
    
  5. Откройте dev.py и dev.py этот материал, который специфичен для разработки, например:

    dev.py:

    DEBUG = True
    ALLOWED_HOSTS = ['localhost']
    ...
    
  6. Откройте prod.py и prod.py материал, относящийся к конкретной продукции, например:

    prod.py:

    DEBUG = False
    ALLOWED_HOSTS = ['www.example.com']
    LOGGING = [...]
    ...
    

Ответ 12

Это мое решение, с разными environements для dev, test и prod

import socket

[...]

DEV_PC = 'PC059'
host_name = socket.gethostname()

if host_name == DEV_PC:
   #do something
   pass
elif [...]