|
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'): |
|
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 def get_all_members(self): |
|
112 return dir(self) |
|
113 |
|
114 class UserSettingsHolder(object): |
|
115 """ |
|
116 Holder for user configured settings. |
|
117 """ |
|
118 # SETTINGS_MODULE doesn't make much sense in the manually configured |
|
119 # (standalone) case. |
|
120 SETTINGS_MODULE = None |
|
121 |
|
122 def __init__(self, default_settings): |
|
123 """ |
|
124 Requests for configuration variables not in this class are satisfied |
|
125 from the module specified in default_settings (if possible). |
|
126 """ |
|
127 self.default_settings = default_settings |
|
128 |
|
129 def __getattr__(self, name): |
|
130 return getattr(self.default_settings, name) |
|
131 |
|
132 def get_all_members(self): |
|
133 return dir(self) + dir(self.default_settings) |
|
134 |
|
135 settings = LazySettings() |
|
136 |