* read json settings (if they exist), use them
* load settings.py which allows to override them again (using some
special code tricks like dynamic loading, environments etc.)
On 30 Dec 2019, at 22:46, Christian González <christian...@nerdocs.at> wrote:
Hello,
--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/3047a7b6-3fa0-d574-4bb6-7842b7aed44a%40nerdocs.at.
<pEpkey.asc>
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/D7000C61-69C0-4E59-9DB8-4BB1413B0C98%40tomforb.es.
Hi all,
thanks for your fast response - it seems that this is not a "ah,
forget it, boooring." theme.
I'll try to answer all (for me) relevant things at once here -
sorry to write such a huge mail.
* A class to read django.conf.settings and add defaults/other logic through properties - for example https://github.com/adamchainz/django-cors-headers/blob/31b9c2ef8a333a40f18081ffc1f1cba9fb34574d/src/corsheaders/conf.py . This has the benefit of easily providing defaults, complex logic such as deriving one value from multiple settings, and being read from settings at runtime rather than import time.
This is a good approach too, but it's not namespaced
automatically. And app settings can't provide and override
settings from other apps. This seems a weird suggest, but when
apps depend on another app it should be able to override settings
for that dependency too (because it "uses" that app anyway).
I am in favour of most libraries adding a single setting that controls them, like DRF has REST_FRAMEWORK. I know django-cors-headers doesn't implement the pattern but this is for legacy reasons since I took it over.
I think this pattern solves your first concern Christian.
No it doesn't completely. I used this pattern myself in GDAPS,
copied from graphene (which copied from DRF). But this does _not_
solve the problem: This pattern creates a per-app settings object
which checks at the time of using (which is anywhere after main
settings.py) if there is a global override of the local app's
variable - and takes the right one. In this way it works. but this
is not very convenient - you always have to ask the right settings
object - it maybe would be more convenient, simpler and easier to
code to just ask for a namespaced setting, e.g. in a dotted path
style.
like settings("django.ROOT_URLCONF") or settings("foo_app.SETTINGA")
This is not a really good approach as it implements
strings.
As for your second concern, I think checks make manual installation of apps easier. If a user adds your app to INSTALLED_APPS, the system checks will run and can highlight any missing/misconfigured settings from following the installation docs. Most libraries take 3 minutes to do the initial install so I'm not sure of the value of automating that step compared to adding system checks.
@Matthew Pava
I have worked with Drupal for a long time before Django, and am maintaining a few sites with Drupal, one of it rather big, with many domains & shared content, 40+ modules, API to ther web services, some modules custom coded. I learned a lot of it, but PHP is really ugly. Django does much better, but, compared with Drupal, it has a few drawbacks. I know, Drupal is a CMS, Django is a framework (which you can build a CMS with) - BUT: Drupal is able (like Wordpress) to add modules/plugins per web download and on-the-fly - it installs modules into place, has a very good hooks system and a plugin manager. It also was a help when I designed GDAPS and was one of my blueprints. Drupal however keeps ALL of it's settings in the database which creates many problems on it's own (development/deployment problems how to sync settings from disk to database and vice versa). I wouldn't do that. Settings in code/conf files is a good thing IMHO.
The package manager in Drupal is composer, yes, and together with GDAPS, you could use GDAPS Django packages exactly the sameway. Just install it using pip/pipenv, and Dajngo/GDAPS finds them automatically.
But this can only be achieved by adding a line to settings.py
(call the plugin manager), like I did:
https://gdaps.readthedocs.io/en/latest/Installation.html#installation
These are just hacks because Django doesn't have declarative
settings.
I suggest that if changing to declarative, it MUST be backwards
compatible, yes. So there could be an _internal_ settings.py which
loads environment variables, the bespoken config file, and like I
said, **if** there is a settings.py in the project, Django could
use it - to override settings in a way just code could do it.
@Jacob Rief and @Tom Forbes
Sure, JSON was just one idea. It's "xml 2.0", and not suited to be written by humans easily. yaml or toml would be better, in fact, in a first approach of GDAPS I used toml as meta config data for my Django plugins. I decided (because there IS no common framework in Django, and I didn't want to add another dependency) to let it go and am using an attribute of AppConfig ATM - code again.
> Some settings must be taken from the environment.
Sure. DJANGO_SECRET_KEY etc. But this could be handled by the "internal" settings.py file.
> So rather than just “allowing people to use JSON files for settings” it would be very interesting to explore what a pluggable settings backend would look like.
Now that's the main point IMHO.
I know Drupal a bit here, and
They struggled until v7. You can read about "Configuration
management" here:
https://www.drupal.org/docs/8/configuration-management/managing-your-sites-configuration
By default, the "active" configuration is stored in the database ("config" table). This is for performance and security reasons. This is the complete configuration for the entire site at that moment. Configuration can be exported and imported as YAML files, either in its entirety, or a single piece of configuration, using Drush and/or Drupal Console config commands or the Configuration Manager. (See below for more details.)
Performance is a good reason here. getting settings from database
is really fast. But I didn't like it. If I would design a settings
backend, I would even make it pluggable... so that the user
doesn't have to know there the settings come from.
from django.conf import settings
if settings.FOO.FOO_SETTING:
pass
the settings object could transparently check if any apps implement a "FOO" named object, and ask that object for "FOO_SETTING". This way the user always could ask the main settings object, but settings would be keeped namespaced.
This is just like **i** would do it - again - just my 2 cents.
BTW - and this is combined with it - Django IMHO needs a hooks system, like Drupal has. each point in code which needs "hooks" has it's own pattern of checking apps (search for modules, attributes in modules etc). Signals are not suitable enough and add complexity to the code structure. The GDAPS approach is an idea on how this "could" look like - even to use per-app settings:
# Dream- and pseudo code (GDAPS integrated in Django ;-) ):
# get interface for settings from Django (now GDAPS)
from drupal.interfaces import ISettings
for settings_object in ISettings:
global_settings.merge(settings_object)
So all plugins implementing ISettings are automatically found and can be merged in a way which needs to be done yet ;-)
Yes, maybe I'm dreaming a bit. Dynamic app loading won't be applied any time soon in Django I suppose, btu settings could be done really better.
If a can help in any way here, maybe even with code, please tell me.
Have a Happy New Year everyone!
Greetings from Salzburg,
Christian
This seems a weird suggest, but when apps depend on another app it should be able to override settings for that dependency too (because it "uses" that app anyway).
--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/06f4e659-70f2-cda1-a59e-35d7d79f3984%40nerdocs.at.
Having said that, I recently stumbled on this package django-configurations by chance, while working on something else. It looks quite promising, as one can use (multiple) class inheritance to merge and combine different settings. As far as I can tell, it lacks the dynamic aspect of your GDAPS idea, so I suppose it would not solve the problem of loading plugins in runtime. But, for the part in which you want to load settings from json/yaml/toml/database/wherever, it might be simpler to piggyback on that project and have Configuration classes that load markup, and a config class that loads from DB (although this would probably be trickier than it looks).
But for me it reminds me of the joke:
Waiter: What would you like to eat?
Guest: I'd like to have a burger with fries, but instead of
the fries please bring me rice,
and instead of the burger I'd like a soup.
If I replace everything the config does, it can do something
else. But it still does not solve my problem at all... which is
easily *changing* the installed apps programmatically - so that,
after a restart - new apps are available. In GDAPS, I only add one
line, if you install GDAPS apps per pip, they are found
automatically and work after a restart. But I think this is
Django's "fault" - it could do better.
What would be really a game changer: in django.conf there are LazySettings and Settings classes, and they currently load from a module (https://github.com/django/django/blob/c574bec0929cd2527268c96a492d25223a9fd576/django/conf/__init__.py#L171), after checking the ENVIRONMENT_VARIABLE.
A quick proposal would be to
1. load the environment variable to get the settings name
2. NEW: look for a declarative settings file and load that
3. if that doesn't exist (or additionally), load the settings
from project's settings.py as usual
This way everything would be completely unchanged and backwards compatible, while adding declarative settings functionality.
This doesn't solve per-app settings - but while loading the declarative config, installed apps would be defined already - and their paths should be possible to determine by then. So *their* declarative settings could be found and merged as well.
This seems a weird suggest, but when apps depend on another app it should be able to override settings for that dependency too (because it "uses" that app anyway).
It does seem weird to suggest. I haven't seen such a use case myself. Can you describe in more detail?
For me, I can only imagine it would violate the "principle of least astonishment" that if I had app A installed for some time, then installed app B on top, app B would change the default or manually configured settings of app A. I would prefer if app B complained (via system check) that I had an incompatible app A configuration.
Maybe you're right. I was about to answer how the system should behave when not thinking in "apps" - which are in a flat hierarchy. In GDAPS I try to think in modules/plugins of ONE application - that's what I try to achieve. Let's explain shortly: My main aim is to create an Open Source Electronic Medical Record - meaning I want to create a base system where maybe 3rd party companies could add their own plugins to the system. Everything based upon django as backend (with a REST/Graphene web API), and variable frontends, let's say a web frontend with Vue.js.
But even when a base module has some "default settings", and I install a module B which overrides that defaults because system behaviour is different when using this module, it doesn't make sense. Such a case should be done in code (module B circumvents the default settings etc.) - but settings merging / hierarchy maybe isn't the best way to go. I also strictly believe in "namespaces are a good thing."
So forget overriding settings, there only remains the easy settings access via one object, which would be great.
I have to say, having settings as Python code is one of the features of Django for me. Being able to calculate settings values, take advantage of Python’s module/class parsing, and so on all make settings more than just a set of dictionary values. I think we would lose a bit of functionality if we chose to reduce them to something that YAML or its ilk knows how to express.
--
You received this message because you are subscribed to a topic in the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-developers/eDdUYM3YN1U/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/3de22278-7bad-4409-a2d1-185792a4375c%40googlegroups.com.