Django: jak zarządzać ustawieniami programistycznymi i produkcyjnymi?
Pracuję nad podstawową aplikacją. Teraz na etapie wdrażania stało się jasne, że potrzebuję zarówno ustawień lokalnych, jak i ustawień produkcyjnych.
Dobrze byłoby wiedzieć, co następuje:
- jak najlepiej radzić sobie z ustawieniami rozwojowymi i produkcyjnymi.
- Jak utrzymać aplikacje takie jak django-debug-toolbar tylko w środowisku deweloperskim.
- Wszelkie inne wskazówki i najlepsze praktyki dotyczące ustawień rozwoju i wdrażania.
15 answers
The DJANGO_SETTINGS_MODULE
zmienna środowiskowa określa, który plik ustawień zostanie załadowany przez Django.
Tworzysz więc oddzielne pliki konfiguracyjne dla odpowiednich środowisk (zauważ, że mogą one oczywiście zarówno import *
z oddzielnego pliku "shared settings"), jak i używać DJANGO_SETTINGS_MODULE
do kontrolowania, którego z nich użyć.
Oto jak:
Jak zaznaczono w dokumentacji Django:
Wartość DJANGO_SETTINGS_MODULE powinna znajdować się w składni ścieżki Pythona, np. mysite.ustawienia. Zauważ, że moduł ustawienia powinien znajdować się na ścieżce wyszukiwania importu Pythona.
Załóżmy więc, że utworzyłeś myapp/production_settings.py
i myapp/test_settings.py
w swoim repozytorium źródłowym.
W takim przypadku ustawisz odpowiednio DJANGO_SETTINGS_MODULE=myapp.production_settings
, aby używać pierwszego i DJANGO_SETTINGS_MODULE=myapp.test_settings
, aby używać drugiego.
Od teraz problem sprowadza się do ustawienia zmiennej środowiskowej DJANGO_SETTINGS_MODULE
.
Ustawienie DJANGO_SETTINGS_MODULE
za pomocą skryptu lub powłoki
Możesz następnie użyć skryptu bootstrap lub menedżer procesów, aby załadować poprawne ustawienia (poprzez ustawienie środowiska), lub po prostu uruchomić go z powłoki przed uruchomieniem Django: export DJANGO_SETTINGS_MODULE=myapp.production_settings
.
Zauważ, że możesz uruchomić ten eksport w dowolnym momencie z powłoki-nie musi ona mieszkać w twoim .bashrc
ani niczym innym.
Ustawienie DJANGO_SETTINGS_MODULE
za pomocą menedżera procesów
Jeśli nie lubisz pisać skryptu bootstrap, który ustawia środowisko (i są bardzo dobre powody, aby tak myśleć!), Polecam korzystanie z procesu kierownik:
-
Supervisor umożliwia przekazywanie zmiennych środowiskowych do zarządzanych procesów za pomocą klucza konfiguracyjnego programu
environment
. -
Honcho (czysty Python odpowiednik Foremana Rubiego) pozwala definiować zmienne środowiskowe w pliku "environment" (
.env
) .
Na koniec zauważ, że możesz skorzystać ze zmiennej PYTHONPATH
, aby zapisać ustawienia w zupełnie innej lokalizacji (np. na serwer produkcyjny, przechowujący je w /etc/
). Pozwala to na oddzielenie konfiguracji od plików aplikacji. Możesz tego chcieć lub nie, zależy to od struktury aplikacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-07 10:41:27
Domyślnie używaj ustawień produkcyjnych, ale Utwórz plik o nazwie settings_dev.py
w tym samym folderze co plik settings.py
. Dodaj tam przesłonięcia, takie jak DEBUG=True
.
Na komputerze, który będzie używany do rozwoju, dodaj to do pliku ~/.bashrc
:
export DJANGO_DEVELOPMENT=true
Na dole pliku settings.py
Dodaj następujący tekst.
# Override production variables if DJANGO_DEVELOPMENT env variable is set
if os.environ.get('DJANGO_DEVELOPMENT'):
from settings_dev import * # or specific overrides
(zauważ, że w Pythonie należy unikać importowania *
)
Domyślnie serwery produkcyjne niczego nie nadpisują. Zrobione!
W porównaniu do innych odpowiedzi, ta jest prostsza, ponieważ nie wymaga aktualizacji PYTHONPATH
, ani Ustawienia DJANGO_SETTINGS_MODULE
, które pozwala Ci pracować tylko nad jednym projektem django na raz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-27 18:17:38
Zazwyczaj mam jeden plik ustawień na środowisko i plik ustawień współdzielonych:
/myproject/
settings.production.py
settings.development.py
shared_settings.py
Każdy z moich plików środowiskowych ma:
try:
from shared_settings import *
except ImportError:
pass
Pozwala mi to w razie potrzeby zastąpić Wspólne Ustawienia(dodając modyfikacje poniżej tej zwrotki).
Następnie wybieram, których plików ustawień użyć, łącząc je z settings.py:
ln -s settings.development.py settings.py
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-19 11:28:31
Tak to robię w 6 prostych krokach:
-
Utwórz folder wewnątrz katalogu projektu i nadaj mu nazwę
settings
.struktura projektu:
myproject/ myapp1/ myapp2/ myproject/ settings/
-
Utwórz cztery pliki Pythona wewnątrz katalogu
settings
mianowicie__init__.py
,base.py
,dev.py
iprod.py
Pliki Ustawień:
settings/ __init__.py base.py prod.py dev.py
-
Otwórz
__init__.py
i wypełnij go następującym treść: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 *
-
Otwórz
base.py
i wypełnij go wszystkimi wspólnymi ustawieniami (które będą używane zarówno w produkcji, jak i w rozwoju.) na przykład: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/'
-
Otwórz
dev.py
i dołącz to, co jest specyficzne dla rozwoju, na przykład:dev.py:
DEBUG = True ALLOWED_HOSTS = ['localhost'] ...
-
Otwórz
prod.py
i dołącz to, co jest produkcją specyficzną dla przykład:prod.py:
DEBUG = False ALLOWED_HOSTS = ['www.example.com'] LOGGING = [...] ...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-06 10:40:16
Tworzy wiele plików settings*.py
, ekstrapolując zmienne, które muszą ulec zmianie w danym środowisku. Następnie na końcu pliku master settings.py
:
try:
from settings_dev import *
except ImportError:
pass
Zachowujesz oddzielne pliki settings_*
dla każdego etapu.
Na górze pliku settings_dev.py
dodaj to:
import sys
globals().update(vars(sys.modules['settings']))
Aby zaimportować zmienne, które należy zmodyfikować.
Ten wpis wiki zawiera więcej pomysłów na podzielenie ustawień.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-19 10:30:56
Używam awesome django-konfiguracje , a wszystkie ustawienia są przechowywane w moim 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
Aby skonfigurować projekt Django, podążałem za docs.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-14 20:56:44
Oto podejście, które stosujemy:
- A
settings
moduł do dzielenia ustawień na wiele plików dla czytelności ; - plik
.env.json
do przechowywania poświadczeń i parametrów, które chcemy wykluczyć z naszego repozytorium git lub które są specyficzne dla środowiska; - an
env.py
file to read the.env.json
file
Biorąc pod uwagę następującą strukturę:
...
.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's 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
...
Z .env.json
Jak:
{
"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",
}
I 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()
Możemy mieć następujące ustawienia:
<!-- 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',
}
}
Korzyści płynące z tego rozwiązania to:
- poświadczenia i konfiguracje specyficzne dla użytkownika dla lokalnego rozwoju bez modyfikowania repozytorium git;
-
konfiguracja specyficzna dla środowiska, możesz mieć na przykład trzy różne środowiska z trzema różnymi
.env.json
Jak dev, stagging i produkcja ; - dane uwierzytelniające nie są w repozytorium
Mam nadzieję, że to pomoże, pozwól mi wiedz, czy widzisz jakieś zastrzeżenia dotyczące tego rozwiązania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-22 21:57:20
Używam struktury plików:
project/
...
settings/
settings/common.py
settings/local.py
settings/prod.py
settings/__init__.py -> local.py
Więc {[2] } jest łączem (ln w Unixie lub mklink w windows) do local.py
lub może być do prod.py
więc konfiguracja jest nadal w module project.settings
jest czysta i zorganizowana, a jeśli chcesz użyć konkretnego config możesz użyć zmiennej środowiskowej DJANGO_SETTINGS_MODULE
do project.settings.prod
jeśli chcesz uruchomić polecenie dla środowiska produkcyjnego.
W plikach prod.py
i local.py
:
from .shared import *
DATABASE = {
...
}
I shared.py
Plik zachowuje się jako globalny bez określonego configs.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-16 18:44:48
Budowanie z cs01 ' s odpowiedź:
Jeśli masz problemy ze zmienną środowiskową, ustaw jej wartość na łańcuch znaków (np. zrobiłem DJANGO_DEVELOPMENT="true"
).
Zmieniłem również przepływ plików cs01 w następujący sposób:
#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
W ten sposób Django nie musi czytać całego pliku ustawień przed uruchomieniem odpowiedniego pliku ustawień. To rozwiązanie jest przydatne, jeśli Twój plik produkcyjny potrzebuje rzeczy, które są tylko na twoim serwerze produkcyjnym.
Uwaga: w Pythonie 3 importowane pliki trzeba mieć dopisane .
(np. from .settings_dev import *
)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-24 14:03:55
Jeśli chcesz zachować 1 plik ustawień, a Twój system operacyjny rozwoju jest inny niż system operacyjny produkcji, możesz umieścić go na dole swojego settings.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
Read more: Jak sprawdzić system operacyjny w Pythonie?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:19
Wydaje się, że odpowiedź została udzielona, jednak metoda, której używam w połączeniu z kontrolą wersji, jest następująca:
Setup a env.py plik w tym samym katalogu co Ustawienia w moim lokalnym środowisku programistycznym, do którego również dodaję .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
Po prostu uważam, że to działa i jest o wiele bardziej eleganckie - z env.py łatwo jest zobaczyć nasze lokalne zmienne środowiskowe i możemy obsłużyć to wszystko bez wielokrotności settings.py pliki lub podobne. Metoda ta pozwala na używanie różnego rodzaju lokalnych zmiennych środowiskowych, których nie chcemy ustawiać na naszym serwerze produkcyjnym. Wykorzystanie .gitignore poprzez kontrolę wersji również wszystko jest bezproblemowo zintegrowane.Użyj settings.py
do produkcji. W tym samym katalogu Utwórz settings_dev.py
dla nadpisań.
# settings_dev.py
from .settings import *
DEBUG = False
Na maszynie deweloperskiej uruchom swoją aplikację Django z:
DJANGO_SETTINGS_MODULE=<your_app_name>.settings_dev python3 manage.py runserver
Na maszynie prod działa tak, jakbyś miał settings.py
i nic więcej.
Zalety
-
settings.py
(używany do produkcji) jest całkowicie agnostyczny wobec faktu, że istnieją jakiekolwiek inne środowiska. - aby zobaczyć różnicę między prod I dev wystarczy spojrzeć na jedną lokalizację -
settings_dev.py
. Nie. trzeba zebrać konfiguracje rozrzucone posettings_prod.py
,settings_dev.py
isettings_shared.py
. - Jeśli ktoś doda ustawienie do twojej konfiguracji prod po rozwiązaniu problemu z produkcją, możesz mieć pewność, że pojawi się ono również w Twojej konfiguracji dev (chyba że zostanie wyraźnie nadpisane). W ten sposób rozbieżność między różnymi plikami konfiguracyjnymi zostanie zminimalizowana.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-25 10:16:34
W przypadku problemu z ustawieniem plików, wybieram skopiowanie
Project
|---__init__.py [ write code to copy setting file from subdir to current dir]
|---settings.py (do not commit this file to git)
|---setting1_dir
| |-- settings.py
|---setting2_dir
| |-- settings.py
Kiedy uruchomisz django,__init _ _ py zostanie uruchomiony. W tym momencie settings.py in setting1_dir
zastąpi settings.py in Project
.
Jak wybrać inny env?
- zmodyfikuj
__init__.py
bezpośrednio. - Utwórz plik bash, aby zmodyfikować
__init__.py
. - zmodyfikuj env w Linuksie, a następnie pozwól
__init__.py
odczytać tę zmienną.
Dlaczego używać w ten sposób?
Ponieważ nie lubię tak wielu plików w tym samym katalogu, zbyt wiele plików będzie mylić innych partnerów i nie bardzo dobrze dla IDE.(IDE nie może znaleźć pliku, którego używamy)
Jeśli nie chcesz widzieć wszystkich tych szczegółów, możesz podzielić projekt na dwie części.
- Stwórz małe narzędzie, takie jak Spring Initializr, tylko do konfiguracji projektu.(do sth like copy file)
- Twój kod projektu
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-09 05:45:57
Używam innej aplikacji.plik yaml do zmiany konfiguracji między środowiskami w Google cloud App engine.
Możesz użyć tego do utworzenia połączenia proxy w poleceniu terminal:
./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:1433
Https://cloud.google.com/sql/docs/sqlserver/connect-admin-proxy#macos-64-bit
Plik: app.yaml
# [START django_app]
service: development
runtime: python37
env_variables:
DJANGO_DB_HOST: '/cloudsql/myproject:myregion:myinstance'
DJANGO_DEBUG: True
handlers:
# This configures Google App Engine to serve the files in the app's static
# directory.
- url: /static
static_dir: static/
# This handler routes all requests not caught above to your main app. It is
# required when static routes are defined, but can be omitted (along with
# the entire handlers section) when there are no static files defined.
- url: /.*
script: auto
# [END django_app]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-23 09:51:45
To jest moje rozwiązanie, z różnymi środowiskami dla dev, test i prod
import socket
[...]
DEV_PC = 'PC059'
host_name = socket.gethostname()
if host_name == DEV_PC:
#do something
pass
elif [...]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-03 09:31:39