It seems that django-configurations provides a number of functionalities:
A method for organising settings via inheritance hierarchies
A bunch of utilities for defining settings based on environment variables, URLs etc.
It's own way of defining and importing settings, via the DJANGO_CONFIGURATION variable, which involves a bit of "magic".
The first two are great, but it seems like this last part is really unrelated, and causes a lot of complexity and issues. The docs say:
Yes, it looks like magic, but it’s also maintainable and non-intrusive
I think this is a bit optimistic. It requires you to change your manage.py, or wsgi.py/asgi.py, so it is quite invasive, it monkey patches BaseCommand, it breaks any script that just uses django.setup(), and also creates a bunch of other bugs, such as:
Is all of this actually necessary, or actually worth it compared to other options?
My idea is that you would not have any import loader (or it would be optional). Instead, you'd have a normal settings.py file, which would contain something like:
from configurations import setup_settings
setup_settings(from_environment_variable='DJANGO_CONFIGURATION')
All of the magic needed would be in that function. It would ideally not do any monkey patching of Django, but it might well do some messing around with sys._getframe(1).f_globals etc. to populate the module.
In other words, you'd have a couple of lines of boilerplate in each project, but only in the settings.py file. The only magic would be that the settings.py module explicitly populates itself in an unusual way, and after that there would be zero consequences for everything else.
Proof of concept - settings.py:
from configurations import setup_settings
setup_settings()
print(A_MAGICALLY_CREATED_SETTING)
configurations/__init__.py:
def setup_settings():
f = sys._getframe(1)
f.f_globals["A_MAGICALLY_CREATED_SETTING"] = "MAGICALLY INJECTED!"
You could also pass in globals() like setup_settings(globals()) for even less magic.
It seems that django-configurations provides a number of functionalities:
The first two are great, but it seems like this last part is really unrelated, and causes a lot of complexity and issues. The docs say:
I think this is a bit optimistic. It requires you to change your
manage.py
, orwsgi.py
/asgi.py
, so it is quite invasive, it monkey patchesBaseCommand
, it breaks any script that just uses django.setup(), and also creates a bunch of other bugs, such as:Is all of this actually necessary, or actually worth it compared to other options?
My idea is that you would not have any import loader (or it would be optional). Instead, you'd have a normal settings.py file, which would contain something like:
All of the magic needed would be in that function. It would ideally not do any monkey patching of Django, but it might well do some messing around with
sys._getframe(1).f_globals
etc. to populate the module.In other words, you'd have a couple of lines of boilerplate in each project, but only in the settings.py file. The only magic would be that the settings.py module explicitly populates itself in an unusual way, and after that there would be zero consequences for everything else.
Proof of concept -
settings.py
:configurations/__init__.py
:You could also pass in
globals()
likesetup_settings(globals())
for even less magic.