|
38
|
1 |
""" |
|
|
2 |
Settings and configuration for Django. |
|
|
3 |
|
|
|
4 |
Values will be read from the module specified by the DJANGO_SETTINGS_MODULE environment |
|
|
5 |
variable, and then from django.conf.global_settings; see the global settings file for |
|
|
6 |
a list of all possible variables. |
|
|
7 |
""" |
|
|
8 |
|
|
|
9 |
import os |
|
|
10 |
import re |
|
|
11 |
import time # Needed for Windows |
|
|
12 |
|
|
|
13 |
from django.conf import global_settings |
|
|
14 |
from django.utils.functional import LazyObject |
|
|
15 |
from django.utils import importlib |
|
|
16 |
|
|
|
17 |
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" |
|
|
18 |
|
|
|
19 |
class LazySettings(LazyObject): |
|
|
20 |
""" |
|
|
21 |
A lazy proxy for either global Django settings or a custom settings object. |
|
|
22 |
The user can manually configure settings prior to using them. Otherwise, |
|
|
23 |
Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE. |
|
|
24 |
""" |
|
|
25 |
def _setup(self): |
|
|
26 |
""" |
|
|
27 |
Load the settings module pointed to by the environment variable. This |
|
|
28 |
is used the first time we need any settings at all, if the user has not |
|
|
29 |
previously configured the settings manually. |
|
|
30 |
""" |
|
|
31 |
try: |
|
|
32 |
settings_module = os.environ[ENVIRONMENT_VARIABLE] |
|
|
33 |
if not settings_module: # If it's set but is an empty string. |
|
|
34 |
raise KeyError |
|
|
35 |
except KeyError: |
|
|
36 |
# NOTE: This is arguably an EnvironmentError, but that causes |
|
|
37 |
# problems with Python's interactive help. |
|
|
38 |
raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE) |
|
|
39 |
|
|
|
40 |
self._wrapped = Settings(settings_module) |
|
|
41 |
|
|
|
42 |
def configure(self, default_settings=global_settings, **options): |
|
|
43 |
""" |
|
|
44 |
Called to manually configure the settings. The 'default_settings' |
|
|
45 |
parameter sets where to retrieve any unspecified values from (its |
|
|
46 |
argument must support attribute access (__getattr__)). |
|
|
47 |
""" |
|
|
48 |
if self._wrapped != None: |
|
|
49 |
raise RuntimeError('Settings already configured.') |
|
|
50 |
holder = UserSettingsHolder(default_settings) |
|
|
51 |
for name, value in options.items(): |
|
|
52 |
setattr(holder, name, value) |
|
|
53 |
self._wrapped = holder |
|
|
54 |
|
|
|
55 |
def configured(self): |
|
|
56 |
""" |
|
|
57 |
Returns True if the settings have already been configured. |
|
|
58 |
""" |
|
|
59 |
return bool(self._wrapped) |
|
|
60 |
configured = property(configured) |
|
|
61 |
|
|
|
62 |
class Settings(object): |
|
|
63 |
def __init__(self, settings_module): |
|
|
64 |
# update this dict from global settings (but only for ALL_CAPS settings) |
|
|
65 |
for setting in dir(global_settings): |
|
|
66 |
if setting == setting.upper(): |
|
|
67 |
setattr(self, setting, getattr(global_settings, setting)) |
|
|
68 |
|
|
|
69 |
# store the settings module in case someone later cares |
|
|
70 |
self.SETTINGS_MODULE = settings_module |
|
|
71 |
|
|
|
72 |
try: |
|
|
73 |
mod = importlib.import_module(self.SETTINGS_MODULE) |
|
|
74 |
except ImportError, e: |
|
|
75 |
raise ImportError("Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)) |
|
|
76 |
|
|
|
77 |
# Settings that should be converted into tuples if they're mistakenly entered |
|
|
78 |
# as strings. |
|
|
79 |
tuple_settings = ("INSTALLED_APPS", "TEMPLATE_DIRS") |
|
|
80 |
|
|
|
81 |
for setting in dir(mod): |
|
|
82 |
if setting == setting.upper(): |
|
|
83 |
setting_value = getattr(mod, setting) |
|
|
84 |
if setting in tuple_settings and type(setting_value) == str: |
|
|
85 |
setting_value = (setting_value,) # In case the user forgot the comma. |
|
|
86 |
setattr(self, setting, setting_value) |
|
|
87 |
|
|
|
88 |
# Expand entries in INSTALLED_APPS like "django.contrib.*" to a list |
|
|
89 |
# of all those apps. |
|
|
90 |
new_installed_apps = [] |
|
|
91 |
for app in self.INSTALLED_APPS: |
|
|
92 |
if app.endswith('.*'): |
|
|
93 |
app_mod = importlib.import_module(app[:-2]) |
|
|
94 |
appdir = os.path.dirname(app_mod.__file__) |
|
|
95 |
app_subdirs = os.listdir(appdir) |
|
|
96 |
app_subdirs.sort() |
|
|
97 |
name_pattern = re.compile(r'[a-zA-Z]\w*') |
|
|
98 |
for d in app_subdirs: |
|
|
99 |
if name_pattern.match(d) and os.path.isdir(os.path.join(appdir, d)): |
|
|
100 |
new_installed_apps.append('%s.%s' % (app[:-2], d)) |
|
|
101 |
else: |
|
|
102 |
new_installed_apps.append(app) |
|
|
103 |
self.INSTALLED_APPS = new_installed_apps |
|
|
104 |
|
|
|
105 |
if hasattr(time, 'tzset') and getattr(self, 'TIME_ZONE'): |
|
|
106 |
# Move the time zone info into os.environ. See ticket #2315 for why |
|
|
107 |
# we don't do this unconditionally (breaks Windows). |
|
|
108 |
os.environ['TZ'] = self.TIME_ZONE |
|
|
109 |
time.tzset() |
|
|
110 |
|
|
|
111 |
class UserSettingsHolder(object): |
|
|
112 |
""" |
|
|
113 |
Holder for user configured settings. |
|
|
114 |
""" |
|
|
115 |
# SETTINGS_MODULE doesn't make much sense in the manually configured |
|
|
116 |
# (standalone) case. |
|
|
117 |
SETTINGS_MODULE = None |
|
|
118 |
|
|
|
119 |
def __init__(self, default_settings): |
|
|
120 |
""" |
|
|
121 |
Requests for configuration variables not in this class are satisfied |
|
|
122 |
from the module specified in default_settings (if possible). |
|
|
123 |
""" |
|
|
124 |
self.default_settings = default_settings |
|
|
125 |
|
|
|
126 |
def __getattr__(self, name): |
|
|
127 |
return getattr(self.default_settings, name) |
|
|
128 |
|
|
|
129 |
def __dir__(self): |
|
|
130 |
return self.__dict__.keys() + dir(self.default_settings) |
|
|
131 |
|
|
|
132 |
# For Python < 2.6: |
|
|
133 |
__members__ = property(lambda self: self.__dir__()) |
|
|
134 |
|
|
|
135 |
settings = LazySettings() |
|
|
136 |
|