File: django_dynaconf_v2.py

package info (click to toggle)
python-dynaconf 3.1.7-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,116 kB
  • sloc: python: 12,959; makefile: 4
file content (127 lines) | stat: -rw-r--r-- 4,171 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"""Dynaconf django extension

In the `django_project/settings.py` put at the very botton of the file:

# HERE STARTS DYNACONF EXTENSION LOAD (Keep at the very bottom of settings.py)
# Read more at https://dynaconf.readthedocs.io/en/latest/guides/django.html
import dynaconf  # noqa
settings = dynaconf.DjangoDynaconf(__name__)  # noqa
# HERE ENDS DYNACONF EXTENSION LOAD (No more code below this line)

Now in the root of your Django project
(the same folder where manage.py is located)

Put your config files `settings.{py|yaml|toml|ini|json}`
and or `.secrets.{py|yaml|toml|ini|json}`

On your projects root folder now you can start as::

    DJANGO_DEBUG='false' \
    DJANGO_ALLOWED_HOSTS='["localhost"]' \
    python manage.py runserver
"""
import inspect
import os
import sys

import dynaconf

try:  # pragma: no cover
    from django import conf
    from django.conf import settings as django_settings

    django_installed = True
except ImportError:  # pragma: no cover
    django_installed = False


def load(django_settings_module_name=None, **kwargs):  # pragma: no cover
    if not django_installed:
        raise RuntimeError(
            "To use this extension django must be installed "
            "install it with: pip install django"
        )

    try:
        django_settings_module = sys.modules[django_settings_module_name]
    except KeyError:
        django_settings_module = sys.modules[
            os.environ["DJANGO_SETTINGS_MODULE"]
        ]

    settings_file = os.path.abspath(django_settings_module.__file__)
    _root_path = os.path.dirname(settings_file)

    # 1) Create the lazy settings object reusing settings_module consts
    options = {
        k: v for k, v in django_settings_module.__dict__.items() if k.isupper()
    }
    options.update(kwargs)
    options.setdefault(
        "SKIP_FILES_FOR_DYNACONF", [settings_file, "dynaconf_merge"]
    )
    options.setdefault("ROOT_PATH_FOR_DYNACONF", _root_path)
    options.setdefault("ENVVAR_PREFIX_FOR_DYNACONF", "DJANGO")
    options.setdefault("ENV_SWITCHER_FOR_DYNACONF", "DJANGO_ENV")
    options.setdefault("ENVIRONMENTS_FOR_DYNACONF", True)
    options.setdefault("load_dotenv", True)
    options.setdefault(
        "default_settings_paths", dynaconf.DEFAULT_SETTINGS_FILES
    )

    class UserSettingsHolder(dynaconf.LazySettings):
        _django_override = True

    lazy_settings = dynaconf.LazySettings(**options)
    dynaconf.settings = lazy_settings  # rebind the settings

    # 2) Set all settings back to django_settings_module for 'django check'
    lazy_settings.populate_obj(django_settings_module)

    # 3) Bind `settings` and `DYNACONF`
    setattr(django_settings_module, "settings", lazy_settings)
    setattr(django_settings_module, "DYNACONF", lazy_settings)

    # 4) keep django original settings
    dj = {}
    for key in dir(django_settings):
        if (
            key.isupper()
            and (key != "SETTINGS_MODULE")
            and key not in lazy_settings.store
        ):
            dj[key] = getattr(django_settings, key, None)
        dj["ORIGINAL_SETTINGS_MODULE"] = django_settings.SETTINGS_MODULE

    lazy_settings.update(dj)

    # 5) Patch django.conf.settings
    class Wrapper:

        # lazy_settings = conf.settings.lazy_settings

        def __getattribute__(self, name):
            if name == "settings":
                return lazy_settings
            if name == "UserSettingsHolder":
                return UserSettingsHolder
            return getattr(conf, name)

    # This implementation is recommended by Guido Van Rossum
    # https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
    sys.modules["django.conf"] = Wrapper()

    # 6) Enable standalone scripts to use Dynaconf
    # This is for when `django.conf.settings` is imported directly
    # on external `scripts` (out of Django's lifetime)
    for stack_item in reversed(inspect.stack()):
        if isinstance(
            stack_item.frame.f_globals.get("settings"), conf.LazySettings
        ):
            stack_item.frame.f_globals["settings"] = lazy_settings

    return lazy_settings


# syntax sugar
DjangoDynaconf = load  # noqa