1
|
|
"""Dynaconf django extension
|
2
|
|
|
3
|
|
In the `django_project/settings.py` put at the very botton of the file:
|
4
|
|
|
5
|
|
# HERE STARTS DYNACONF EXTENSION LOAD (Keep at the very bottom of settings.py)
|
6
|
|
# Read more at https://dynaconf.readthedocs.io/en/latest/guides/django.html
|
7
|
|
import dynaconf # noqa
|
8
|
|
settings = dynaconf.DjangoDynaconf(__name__) # noqa
|
9
|
|
# HERE ENDS DYNACONF EXTENSION LOAD (No more code below this line)
|
10
|
|
|
11
|
|
Now in the root of your Django project
|
12
|
|
(the same folder where manage.py is located)
|
13
|
|
|
14
|
|
Put your config files `settings.{py|yaml|toml|ini|json}`
|
15
|
|
and or `.secrets.{py|yaml|toml|ini|json}`
|
16
|
|
|
17
|
|
On your projects root folder now you can start as::
|
18
|
|
|
19
|
|
DJANGO_DEBUG='false' \
|
20
|
|
DJANGO_ALLOWED_HOSTS='["localhost"]' \
|
21
|
|
python manage.py runserver
|
22
|
|
"""
|
23
|
2
|
import inspect
|
24
|
2
|
import os
|
25
|
2
|
import sys
|
26
|
|
|
27
|
2
|
import dynaconf
|
28
|
|
|
29
|
|
try: # pragma: no cover
|
30
|
|
from django import conf
|
31
|
|
from django.conf import settings as django_settings
|
32
|
|
|
33
|
|
django_installed = True
|
34
|
|
except ImportError: # pragma: no cover
|
35
|
|
django_installed = False
|
36
|
|
|
37
|
|
|
38
|
|
def load(django_settings_module_name=None, **kwargs): # pragma: no cover
|
39
|
|
if not django_installed:
|
40
|
|
raise RuntimeError(
|
41
|
|
"To use this extension django must be installed "
|
42
|
|
"install it with: pip install django"
|
43
|
|
)
|
44
|
|
|
45
|
|
try:
|
46
|
|
django_settings_module = sys.modules[django_settings_module_name]
|
47
|
|
except KeyError:
|
48
|
|
django_settings_module = sys.modules[
|
49
|
|
os.environ["DJANGO_SETTINGS_MODULE"]
|
50
|
|
]
|
51
|
|
|
52
|
|
settings_file = os.path.abspath(django_settings_module.__file__)
|
53
|
|
_root_path = os.path.dirname(settings_file)
|
54
|
|
|
55
|
|
# 1) Create the lazy settings object reusing settings_module consts
|
56
|
|
options = {
|
57
|
|
k: v for k, v in django_settings_module.__dict__.items() if k.isupper()
|
58
|
|
}
|
59
|
|
options.update(kwargs)
|
60
|
|
options.setdefault(
|
61
|
|
"SKIP_FILES_FOR_DYNACONF", [settings_file, "dynaconf_merge"]
|
62
|
|
)
|
63
|
|
options.setdefault("ROOT_PATH_FOR_DYNACONF", _root_path)
|
64
|
|
options.setdefault("ENVVAR_PREFIX_FOR_DYNACONF", "DJANGO")
|
65
|
|
options.setdefault("ENV_SWITCHER_FOR_DYNACONF", "DJANGO_ENV")
|
66
|
|
options.setdefault("ENVIRONMENTS_FOR_DYNACONF", True)
|
67
|
|
options.setdefault("load_dotenv", True)
|
68
|
|
options.setdefault(
|
69
|
|
"default_settings_paths", dynaconf.DEFAULT_SETTINGS_FILES
|
70
|
|
)
|
71
|
|
|
72
|
|
lazy_settings = dynaconf.LazySettings(**options)
|
73
|
|
dynaconf.settings = lazy_settings # rebind the settings
|
74
|
|
|
75
|
|
# 2) Set all settings back to django_settings_module for 'django check'
|
76
|
|
lazy_settings.populate_obj(django_settings_module)
|
77
|
|
|
78
|
|
# 3) Bind `settings` and `DYNACONF`
|
79
|
|
setattr(django_settings_module, "settings", lazy_settings)
|
80
|
|
setattr(django_settings_module, "DYNACONF", lazy_settings)
|
81
|
|
|
82
|
|
# 4) keep django original settings
|
83
|
|
dj = {}
|
84
|
|
for key in dir(django_settings):
|
85
|
|
if (
|
86
|
|
key.isupper()
|
87
|
|
and (key != "SETTINGS_MODULE")
|
88
|
|
and key not in lazy_settings.store
|
89
|
|
):
|
90
|
|
dj[key] = getattr(django_settings, key, None)
|
91
|
|
dj["ORIGINAL_SETTINGS_MODULE"] = django_settings.SETTINGS_MODULE
|
92
|
|
|
93
|
|
lazy_settings.update(dj)
|
94
|
|
|
95
|
|
# 5) Patch django.conf.settings
|
96
|
|
class Wrapper(object):
|
97
|
|
|
98
|
|
# lazy_settings = conf.settings.lazy_settings
|
99
|
|
|
100
|
|
def __getattribute__(self, name):
|
101
|
|
if name == "settings":
|
102
|
|
return lazy_settings
|
103
|
|
else:
|
104
|
|
return getattr(conf, name)
|
105
|
|
|
106
|
|
# This implementation is recommended by Guido Van Rossum
|
107
|
|
# https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
|
108
|
|
sys.modules["django.conf"] = Wrapper()
|
109
|
|
|
110
|
|
# 6) Enable standalone scripts to use Dynaconf
|
111
|
|
# This is for when `django.conf.settings` is imported directly
|
112
|
|
# on external `scripts` (out of Django's lifetime)
|
113
|
|
for stack_item in reversed(inspect.stack()):
|
114
|
|
if isinstance(
|
115
|
|
stack_item.frame.f_globals.get("settings"), conf.LazySettings
|
116
|
|
):
|
117
|
|
stack_item.frame.f_globals["settings"] = lazy_settings
|
118
|
|
|
119
|
|
return lazy_settings
|
120
|
|
|
121
|
|
|
122
|
|
# syntax sugar
|
123
|
2
|
DjangoDynaconf = load # noqa
|