2 |
2 |
3 from django.conf import settings |
3 from django.conf import settings |
4 from django.core.exceptions import ImproperlyConfigured |
4 from django.core.exceptions import ImproperlyConfigured |
5 from django.utils.datastructures import SortedDict |
5 from django.utils.datastructures import SortedDict |
6 from django.utils.importlib import import_module |
6 from django.utils.importlib import import_module |
7 |
7 from django.utils.module_loading import module_has_submodule |
|
8 |
|
9 import imp |
8 import sys |
10 import sys |
9 import os |
11 import os |
10 import threading |
12 import threading |
11 |
13 |
12 __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models', |
14 __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models', |
68 Loads the app with the provided fully qualified name, and returns the |
71 Loads the app with the provided fully qualified name, and returns the |
69 model module. |
72 model module. |
70 """ |
73 """ |
71 self.handled[app_name] = None |
74 self.handled[app_name] = None |
72 self.nesting_level += 1 |
75 self.nesting_level += 1 |
|
76 app_module = import_module(app_name) |
73 try: |
77 try: |
74 models = import_module('.models', app_name) |
78 models = import_module('.models', app_name) |
75 except ImportError: |
79 except ImportError: |
76 self.nesting_level -= 1 |
80 self.nesting_level -= 1 |
77 if can_postpone: |
81 # If the app doesn't have a models module, we can just ignore the |
78 # Either the app has no models, or the package is still being |
82 # ImportError and return no models for it. |
79 # imported by Python and the model module isn't available yet. |
83 if not module_has_submodule(app_module, 'models'): |
80 # We will check again once all the recursion has finished (in |
84 return None |
81 # populate). |
85 # But if the app does have a models module, we need to figure out |
82 self.postponed.append(app_name) |
86 # whether to suppress or propagate the error. If can_postpone is |
83 return None |
87 # True then it may be that the package is still being imported by |
|
88 # Python and the models module isn't available yet. So we add the |
|
89 # app to the postponed list and we'll try it again after all the |
|
90 # recursion has finished (in populate). If can_postpone is False |
|
91 # then it's time to raise the ImportError. |
|
92 else: |
|
93 if can_postpone: |
|
94 self.postponed.append(app_name) |
|
95 return None |
|
96 else: |
|
97 raise |
|
98 |
84 self.nesting_level -= 1 |
99 self.nesting_level -= 1 |
85 if models not in self.app_store: |
100 if models not in self.app_store: |
86 self.app_store[models] = len(self.app_store) |
101 self.app_store[models] = len(self.app_store) |
87 return models |
102 return models |
88 |
103 |
120 if mod is None: |
135 if mod is None: |
121 if emptyOK: |
136 if emptyOK: |
122 return None |
137 return None |
123 else: |
138 else: |
124 return mod |
139 return mod |
125 raise ImproperlyConfigured, "App with label %s could not be found" % app_label |
140 raise ImproperlyConfigured("App with label %s could not be found" % app_label) |
126 finally: |
141 finally: |
127 self.write_lock.release() |
142 self.write_lock.release() |
128 |
143 |
129 def get_app_errors(self): |
144 def get_app_errors(self): |
130 "Returns the map of known problems with the INSTALLED_APPS." |
145 "Returns the map of known problems with the INSTALLED_APPS." |
131 self._populate() |
146 self._populate() |
132 return self.app_errors |
147 return self.app_errors |
133 |
148 |
134 def get_models(self, app_mod=None): |
149 def get_models(self, app_mod=None, include_auto_created=False, include_deferred=False): |
135 """ |
150 """ |
136 Given a module containing models, returns a list of the models. |
151 Given a module containing models, returns a list of the models. |
137 Otherwise returns a list of all installed models. |
152 Otherwise returns a list of all installed models. |
138 """ |
153 |
|
154 By default, auto-created models (i.e., m2m models without an |
|
155 explicit intermediate table) are not included. However, if you |
|
156 specify include_auto_created=True, they will be. |
|
157 |
|
158 By default, models created to satisfy deferred attribute |
|
159 queries are *not* included in the list of models. However, if |
|
160 you specify include_deferred, they will be. |
|
161 """ |
|
162 cache_key = (app_mod, include_auto_created, include_deferred) |
|
163 try: |
|
164 return self._get_models_cache[cache_key] |
|
165 except KeyError: |
|
166 pass |
139 self._populate() |
167 self._populate() |
140 if app_mod: |
168 if app_mod: |
141 return self.app_models.get(app_mod.__name__.split('.')[-2], SortedDict()).values() |
169 app_list = [self.app_models.get(app_mod.__name__.split('.')[-2], SortedDict())] |
142 else: |
170 else: |
143 model_list = [] |
171 app_list = self.app_models.itervalues() |
144 for app_entry in self.app_models.itervalues(): |
172 model_list = [] |
145 model_list.extend(app_entry.values()) |
173 for app in app_list: |
146 return model_list |
174 model_list.extend( |
|
175 model for model in app.values() |
|
176 if ((not model._deferred or include_deferred) |
|
177 and (not model._meta.auto_created or include_auto_created)) |
|
178 ) |
|
179 self._get_models_cache[cache_key] = model_list |
|
180 return model_list |
147 |
181 |
148 def get_model(self, app_label, model_name, seed_cache=True): |
182 def get_model(self, app_label, model_name, seed_cache=True): |
149 """ |
183 """ |
150 Returns the model matching the given app_label and case-insensitive |
184 Returns the model matching the given app_label and case-insensitive |
151 model_name. |
185 model_name. |
175 # .pyc or .pyo the second time, ignore the extension when |
209 # .pyc or .pyo the second time, ignore the extension when |
176 # comparing. |
210 # comparing. |
177 if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]: |
211 if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]: |
178 continue |
212 continue |
179 model_dict[model_name] = model |
213 model_dict[model_name] = model |
|
214 self._get_models_cache.clear() |
180 |
215 |
181 cache = AppCache() |
216 cache = AppCache() |
182 |
217 |
183 # These methods were always module level, so are kept that way for backwards |
218 # These methods were always module level, so are kept that way for backwards |
184 # compatibility. |
219 # compatibility. |