टीएल; डीआर: चाल किसी में भी os.environment
आयात करने से पहले संशोधित करने के लिए है , यह चीजों को बहुत सरल करेगा।settings/base.py
settings/<purpose>.py
बस इन सभी इंटरवेटिंग फाइलों के बारे में सोचने से मुझे सिरदर्द होता है। संयोजन करना, आयात करना (कभी-कभी सशर्त रूप से), ओवरराइडिंग, पहले से ही मामले की DEBUG
सेटिंग में जो कुछ भी सेट किया गया था उसे बाद में बदलना। कितना बुरा सपना!
वर्षों से मैं सभी अलग-अलग समाधानों के माध्यम से गया। वे सभी कुछ काम करते हैं, लेकिन प्रबंधन करने के लिए बहुत दर्दनाक हैं। WTF! क्या हमें वास्तव में उस परेशानी की आवश्यकता है? हमने सिर्फ एक settings.py
फाइल से शुरुआत की । अब हमें सही क्रम में इन सभी को एक साथ संयोजित करने के लिए एक दस्तावेज की आवश्यकता है!
मुझे आशा है कि मैं अंत में (मेरे) मीठे स्थान को नीचे दिए गए समाधान के साथ मारूंगा।
आइए लक्ष्यों को पुन: लागू करें (कुछ सामान्य, कुछ मेरा)
रहस्यों को गुप्त रखें - उन्हें रेपो में संग्रहीत न करें!
पर्यावरण सेटिंग्स, 12 कारक शैली के माध्यम से कुंजी और रहस्य सेट / पढ़ें ।
समझदार कमियां है चूक। आदर्श रूप से स्थानीय विकास के लिए आपको चूक के अलावा और कुछ भी करने की आवश्यकता नहीं है।
… लेकिन उत्पादन को सुरक्षित रखने की कोशिश करें। उत्पादन के लिए सुरक्षित डिफ़ॉल्ट सेटिंग्स को समायोजित करने के लिए याद रखने की तुलना में, स्थानीय रूप से एक सेटिंग ओवरराइड को याद करना बेहतर है।
DEBUG
एक तरह से चालू / बंद करने की क्षमता है जो अन्य सेटिंग्स पर प्रभाव डाल सकती है (जैसे कि जावास्क्रिप्ट संपीड़ित का उपयोग करना या नहीं)।
उद्देश्य सेटिंग्स के बीच स्विच करना, जैसे स्थानीय / परीक्षण / स्टेजिंग / उत्पादन, केवल DJANGO_SETTINGS_MODULE
कुछ और पर आधारित होना चाहिए ।
... लेकिन पर्यावरण सेटिंग्स जैसे माध्यम से आगे के पैरामीटरकरण की अनुमति दें DATABASE_URL
।
… उन्हें अलग-अलग उद्देश्य सेटिंग्स का उपयोग करने और स्थानीय स्तर पर उन्हें साइड से चलाने की अनुमति देता है, जैसे। उत्पादन डेटाबेस या धूम्रपान परीक्षण संपीड़ित स्टाइल शीट तक पहुंचने के लिए स्थानीय डेवलपर मशीन पर उत्पादन सेटअप।
यदि कोई पर्यावरण चर स्पष्ट रूप से सेट नहीं किया जाता है (न्यूनतम मूल्य पर खाली मूल्य की आवश्यकता होती है), विशेष रूप से उत्पादन में, जैसे। EMAIL_HOST_PASSWORD
।
Django-admin startproject केDJANGO_SETTINGS_MODULE
दौरान manage.py में डिफ़ॉल्ट सेट का जवाब दें
, एक न्यूनतम करने के लिए सशर्त रखें अगर हालत है यह मकसद पर्यावरण, जुड़े ठान लिया सेटिंग्स फ़ाइल में ओवरराइड सेटिंग्स (उत्पादन सेट लॉग फ़ाइल और यह के रोटेशन के लिए जैसे।) लिखें।
नहीं है
Django को DJANGO_SETTINGS_MODULE सेटिंग फ़ाइल के रूप में पढ़ने न दें।
ओह! यह कैसे मेटा है यह सोचें। यदि आपको एक फाइल करने की आवश्यकता है (जैसे docker env) एक django प्रक्रिया को शुरू करने से पहले पर्यावरण में पढ़ें।
अपने प्रोजेक्ट / ऐप कोड में DJANGO_SETTINGS_MODULE को ओवरराइड न करें, जैसे। होस्टनाम या प्रक्रिया के नाम पर आधारित है।
यदि आप पर्यावरण चर (जैसे के लिए setup.py test
) सेट करने के लिए आलसी हैं तो अपना प्रोजेक्ट कोड चलाने से पहले इसे टूलिंग में करें।
जादू से बचें और कैसे django पढ़ता है यह सेटिंग्स है, सेटिंग्स को प्रीप्रोसेस करें लेकिन बाद में हस्तक्षेप न करें।
कोई जटिल तर्क आधारित बकवास नहीं। कॉन्फ़िगरेशन को ठीक किया जाना चाहिए और मक्खी पर गणना नहीं की जानी चाहिए। एक कमबैक चूक प्रदान करना यहां पर्याप्त तर्क है।
क्या आप वास्तव में डिबग करना चाहते हैं, क्यों स्थानीय स्तर पर आपके पास सेटिंग्स का सही सेट है लेकिन एक रिमोट सर्वर पर उत्पादन में, एक सौ मशीनों पर, कुछ अलग तरह से गणना की जाती है? ओह! यूनिट परीक्षण? सेटिंग्स के लिए? गंभीरता से?
समाधान
मेरी रणनीति में उत्कृष्ट django-environini
शैली फ़ाइलों के साथ उपयोग किया जाता है , os.environment
स्थानीय विकास के लिए चूक प्रदान करता है, कुछ न्यूनतम और छोटी settings/<purpose>.py
फाइलें जो एक
import settings/base.py
AFTERos.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
केवल अजगर पर लागू होंगे यदि वे पर्यावरण और फ़ाइल से MISSING कर रहे हैं।
ये हमारी प्रोडक्शन डिफॉल्ट होंगी, इन्हें पर्यावरण या फाइल में डालने की जरूरत नहीं है, लेकिन जरूरत पड़ने पर इन्हें ओवरराइड किया जा सकता है। साफ!
सेटिंग्स / 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
और यहां तक कि पर्यावरण सेटिंग द्वारा इसे ओवरराइड किया जा सकता है! वाह!
वास्तव में हमारे पास महत्व का एक मिश्रित पदानुक्रम है:
- सेटिंग्स / .py - उद्देश्य के आधार पर चूक सेट करता है, रहस्यों को संग्रहीत नहीं करता है
- सेटिंग / बेस-थ्रू - अधिकतर पर्यावरण द्वारा नियंत्रित होती है
- प्रक्रिया पर्यावरण सेटिंग्स - 12 कारक बच्चे!
- सेटिंग्स / .env - आसान स्टार्टअप के लिए स्थानीय चूक