-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 Hi folks,
On Tue, May 07, 2019 at 10:53:37PM +0200, Aymeric Augustin wrote: > If we're only talking about providing default values for settings, currently > there are two straightforward solutions: > > 1. Like Adam suggested, access settings like this: getattr(settings, > 'MY_SETTING', 'my_default'). > > This works well when you access settings just once, probably at import time, > and cache their value. > > Here's an example: > https://github.com/aaugustin/django-sesame/blob/070cdb3fcdfa6c7310d7461add328a8095148ff1/sesame/backends.py#L27-L34 > > <https://github.com/aaugustin/django-sesame/blob/070cdb3fcdfa6c7310d7461add328a8095148ff1/sesame/backends.py#L27-L34> This approach, however, makes it impossible to use the decorators and context managers from django.test that override settings. Of course, there are other ways to tune those knobs in tests, but it takes away a standard solution provided by the framework. > 2. Set a default value at import time: > > # apps.py > > from django.apps import AppConfig > from django.conf import settings > > class MyAppConfig(AppConfig): > name = 'my_app' > verbose_name = "..." > > def ready(self): > if not hasattr(settings, 'MY_SETTING'): > settings.MY_SETTING = 'my_default' > > If you have many settings, you can define defaults in a DEFAULT_SETTINGS dict > and do this: > > def ready(self): > for setting_name, default_value in DEFAULT_SETTINGS: > if not hasattr(settings, setting_name): > setattr(settings, setting_name, default_value) Nice, I guess it's been a while since I spent any brain cycles on this topic, but this solution seems much less tedious than what I'd seen back in the days of Django 1.4. Almost feels good enough, except for the fact that it goes against what the docs say about modifying settings. > > On 7 May 2019, at 17:15, Christian González <[email protected]> > > wrote: > > > > I myself am using an implementation like DRF does it: > > > > https://github.com/encode/django-rest-framework/blob/e16273a6584f9657c1e5c388558e9c5c92e7ba38/rest_framework/settings.py > > > > <https://github.com/encode/django-rest-framework/blob/e16273a6584f9657c1e5c388558e9c5c92e7ba38/rest_framework/settings.py> > > They create a class "APISettings", and mimic the Django behaviour. > > > > This is yet another approach. DRF relies on a single Django setting which is > a dict containing all individual DRF settings. Then it converts that Django > setting to an object and uses this abstraction to access individual settings > as properties. This seems to have become one of the current best practices, but it requires each reusable package that goes down this road to include a bunch of boilerplate just to deal with default values for settings. I suppose that boilerplate could be factored out into its own reusable package, but my gut tells me that there must be a better way to handle something as fundamental as providing defaults for settings. Definitely a very subjective claim, but I just feel like this is something that should be the responsibility of the framework itself. > Here we're talking about something slightly different: formalizing how an > application can declare default values for its own settings — essentially a > per-app equivalent of Django's global_settings.py. To do this properly, we > need two things: > > - a good convention for declaring these settings: I would find it elegant to > consider every uppercase class attribute of an AppConfig class as a setting, > but that might be too magic (and perhaps backwards-incompatible); I definitely agree that this feels too magic-y. Maybe introducing a class attribute such as “DEFAULT_SETTINGS” that would hold a dictionary could work, though? > - a way to insert them properly into the settings object: I tried to figure > out how LazySettings and friends handle global_settings, unfortunately there > are more use cases than I was willing to untangle tonight. Another thing to possibly consider, what should happen if multiple packages try to provide different defaults for the same setting? I mean, of course, this has kind of been floated in this thread already, but it would add one more item to the list of things affected by the order of INSTALLED_APPS. Cheers, Michal -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEUX01Y24NsLRJUN8tcDtP8g8z+SUFAlzSo6gACgkQcDtP8g8z +SX2iw//bKFrh4tfq2k1gefcSDzhOBclqK4e7er3hwq6bRhevLvIgqVo/i3pwxlj qSVop7ZnbnNk60xsPXLzzlEokkj+QDwldAUsaswckHmdP7zs6UiYWXzvQYc7ufpA /+lcF3LHrBdBBn77Ip0760KxRPX5kjC0gCPSLKPpiBKxwb+31jkjLHkgIzHiYmUL VGzpxDxkL1qLNafefXgezL7+mcUb6Mgj+jnYe+zIWGjDN8HBSQfNcALiyHWY9p5q SCMP2+dH4wL/CsTk8eUEZZwxjlk1X5t2WuoDUxZCqybf9hJG85SjqHGbwnFZI0ar aE9BMEy+e7brZYO3sX3QFoMHM8I0PUBPIPLbQtuEDJdnp9r69TnyNDL4kA/b9T4P MHlta99sOe0VGaXV9LoANypJVVAiIQGU3Wxz9EVdu7g+Fdd2Y3THwaWaKes6r6nC 295lnfJP0MEIO81VDTal571Zqkw+kpm0P4uJVPlI9xgnglHoYOU0Er85ajkopqSl UzI1X7s1GXbfBvd0Ejc3NNyhZcaNOXx0LYkxXsGRd2F/WBluj9neJpZAhbrNBIdk eeAeZa1akIs8mQgObFSLSIxTGK5L/M5R0/cLlSQStOtvFmD7mJSXLM08CbjNWVlk plR85tQ+JNKyxjrAKj7xO7Ha0g7Oo/U9AnkIQwXTSrxncjTEKu0= =2yXl -----END PGP SIGNATURE----- -- 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 [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/20190508093848.rvruv3qdw6vd22m3%40koniiiik.org. For more options, visit https://groups.google.com/d/optout.
