Django default settings convention for pluggable app?

后端 未结 5 1064
广开言路
广开言路 2020-12-14 06:49

What\'s a djangonautic way of handling default settings in an app if one isn\'t defined in settings.py?

I\'ve currently placed a default_settings<

5条回答
  •  生来不讨喜
    2020-12-14 07:17

    It seems that every solution I see there tends to create an internal copy of application settings, proxy, wrap or whatever. This is confusing and creates problems when settings are modified in run time like they do in tests.

    To me all settings belong in django.conf.settings and only there. You should not read them from somewhere else nor copy it for later use (as they may change). You should set them once and don't bother about defaults later on.

    I understand the impulse to drop the app prefix when app setting is used internally, but this also is IMHO a bad idea. When in trouble looking for SOME_APP_FOO will not yield results, as it's used just as FOO internally. Confusing right? And for what, few letters? Remember that explicit is better?

    IMHO the best way is to just set those defaults in Django's own settings, and why don't use piping that is already there? No module import hooks or hijacking models.py being always imported to initialize some extra and complicated meta class piping.

    Why not use AppConfig.ready for setting defaults?

    class FooBarConfig(AppConfig):
        name = 'foo_bar'
    
        def ready(self):
            from django.conf import settings
            settings = settings._wrapped.__dict__
            settings.setdefault('FOO_BAR_SETTING', 'whatever')
    

    Or better yet define them in clean simple way in a separate module and import them as (or close to how) Settings class does it:

    class FooBarConfig(AppConfig):
        name = 'foo_bar'
    
        def ready(self):
            from . import app_settings as defaults
            from django.conf import settings
            for name in dir(defaults):
                if name.isupper() and not hasattr(settings, name):
                    setattr(settings, name, getattr(defaults, name))
    

    I'm not sure use of __dict__ is the best solution, but you get the idea, you can always user hasattr/setattr combo to get the efect.

    This way your app settings are:

    1. exposed to others — if they should rely on them in some rare cases, if of course apps are configured in order rely on each other
    2. read normally as any other setting
    3. nicely declared in their own module
    4. lazy enough
    5. controlled how they're are set in django.conf.settings — you can implement some transposition of names if you want to

    PS. There is a warning about not modifying settings in run time but it does not explain why. So I think this one time, during initialization may be a reasonable exception ;)

    PS2. Don't name the separate module just settings as this may get confusing when you import settings from django.conf.

提交回复
热议问题