django settings per application - best practice?

2019-03-14 07:32发布

问题:

this is somewhat related to this question
Why is django's settings object a LazyObject?

In my django project i have several applications. Each application can have its own non-trivial settings file.

proj/
    proj/
         settings.py
    app/
         settings.py
         views.py

What is the general best practice here?
should app/settings.py do

from django.conf import settings
APP_SETTING= lambda: settings.getattr('APP_SETTING', 'custom_value')
PROJ_SETTING= lambda: settings.PROJ_SETTING

and then in app/views.py do

import .settings 
X = settings.APP_SETTING
Y = settings.PROJ_SETTING

or should I be modifying the django lazy settings object in app/settings.py as per the django coding style?

from django.conf import settings
# not even sure how I would check for a default value that was specified in proj/settings.py
settings.configure(APP_SETTING='custom_value')

and then each app/views.py just consumes proj/settings.py via django.conf settings?

from django.conf import settings
X = settings.APP_SETTING
Y = settings.PROJ_SETTING

There are obviously quite a few other permutations but I think my intent is clear.
Thanks in advance.

回答1:

The simplest solution is to use the getattr(settings, 'MY_SETTING', 'my_default') trick that you mention youself. It can become a bit tedious to have to do this in multiple places, though.

Extra recommendation: use a per-app prefix like MYAPP_MY_SETTING.

There is a django app, however, that gets rid of the getattr and that handles the prefix for you. See http://django-appconf.readthedocs.org/en/latest/

Normally you create a conf.py per app with contents like this:

from django.conf import settings
from appconf import AppConf

class MyAppConf(AppConf):
    SETTING_1 = "one"
    SETTING_2 = (
        "two",
    )

And in your code:

from myapp.conf import settings

def my_view(request):
    return settings.MYAPP_SETTINGS_1  # Note the handy prefix

Should you need to customize the setting in your site, a regular entry in your site's settings.py is all you need to do:

MYAPP_SETTINGS_1 = "four, four I say"


回答2:

Not sure about best practices but I don't have any problems with following style:

proj/settings.py

OPTION_A = 'value'

# or with namespace
APP_NAMESPACE = 'APP'
APP_OPTION_B = 4

app/settings.py

from django.conf import settings
from django.utils.functional import SimpleLazyObject

OPTION_A = getattr(settings, 'OPTION_A', 'default_value')

# or with namespace
NAMESPACE = getattr(settings, APP_NAMESPACE, 'APP')
OPTION_B = getattr(settings, '_'.join([NAMESPACE, 'OPTION_B']), 'default_value')
OPTION_C = getattr(settings, '_'.join([NAMESPACE, 'OPTION_C']), None)
if OPTION_C is None:
    raise ImproperlyConfigured('...')

# lazy option with long initialization
OPTION_D = SimpleLazyObject(lambda: open('file.txt').read())

app/views.py

from .settings import OPTION_A, OPTION_B
# or
from . import settings as app_settings
app_settings.OPTION_C
app_settings.OPTION_D  # initialized on access