diff options
| author | Aymeric Augustin <aymeric.augustin@m4x.org> | 2013-12-31 16:23:42 +0100 |
|---|---|---|
| committer | Aymeric Augustin <aymeric.augustin@m4x.org> | 2013-12-31 17:30:58 +0100 |
| commit | c40209dcc09f19524fb85251f39a4051491bbec0 (patch) | |
| tree | f7788f18e608acf0befab73b3391fea4c21a7066 /django | |
| parent | 5dfec4e23b4a3b81f8ec19bf0cf45147ad6b18e5 (diff) | |
Made it possible to change an application's label in its configuration.
Fixed #21683.
Diffstat (limited to 'django')
| -rw-r--r-- | django/apps/registry.py | 21 | ||||
| -rw-r--r-- | django/db/migrations/state.py | 4 | ||||
| -rw-r--r-- | django/db/models/base.py | 40 |
3 files changed, 48 insertions, 17 deletions
diff --git a/django/apps/registry.py b/django/apps/registry.py index 317bde33fe..7ff1c6625d 100644 --- a/django/apps/registry.py +++ b/django/apps/registry.py @@ -201,6 +201,27 @@ class Apps(object): app_config = self.app_configs.get(app_name.rpartition(".")[2]) return app_config is not None and app_config.name == app_name + def get_containing_app_config(self, object_name): + """ + Look for an app config containing a given object. + + object_name is the dotted Python path to the object. + + Returns the app config for the inner application in case of nesting. + Returns None if the object isn't in any registered app config. + + It's safe to call this method at import time, even while the registry + is being populated. + """ + candidates = [] + for app_config in self.app_configs.values(): + if object_name.startswith(app_config.name): + subpath = object_name[len(app_config.name):] + if subpath == '' or subpath[0] == '.': + candidates.append(app_config) + if candidates: + return sorted(candidates, key=lambda ac: -len(ac.name))[0] + def get_registered_model(self, app_label, model_name): """ Similar to get_model(), but doesn't require that an app exists with diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py index ff2e26c7a0..3bc7837089 100644 --- a/django/db/migrations/state.py +++ b/django/db/migrations/state.py @@ -76,9 +76,7 @@ class AppConfigStub(AppConfig): Stubs a Django AppConfig. Only provides a label and a dict of models. """ def __init__(self, label): - self.label = label - self.path = None - super(AppConfigStub, self).__init__(None, None) + super(AppConfigStub, self).__init__(label, None) def import_models(self, all_models): self.models = all_models diff --git a/django/db/models/base.py b/django/db/models/base.py index 03f1e8b693..0de21fafc9 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -86,23 +86,35 @@ class ModelBase(type): meta = attr_meta base_meta = getattr(new_class, '_meta', None) + # Look for an application configuration to attach the model to. + app_config = apps.get_containing_app_config(module) + if getattr(meta, 'app_label', None) is None: - # Figure out the app_label by looking one level up from the package - # or module named 'models'. If no such package or module exists, - # fall back to looking one level up from the module this model is - # defined in. - # For 'django.contrib.sites.models', this would be 'sites'. - # For 'geo.models.places' this would be 'geo'. + if app_config is None: + # If the model is imported before the configuration for its + # application is created (#21719), or isn't in an installed + # application (#21680), use the legacy logic to figure out the + # app_label by looking one level up from the package or module + # named 'models'. If no such package or module exists, fall + # back to looking one level up from the module this model is + # defined in. + + # For 'django.contrib.sites.models', this would be 'sites'. + # For 'geo.models.places' this would be 'geo'. + + model_module = sys.modules[new_class.__module__] + package_components = model_module.__name__.split('.') + package_components.reverse() # find the last occurrence of 'models' + try: + app_label_index = package_components.index(MODELS_MODULE_NAME) + 1 + except ValueError: + app_label_index = 1 + kwargs = {"app_label": package_components[app_label_index]} + + else: + kwargs = {"app_label": app_config.label} - model_module = sys.modules[new_class.__module__] - package_components = model_module.__name__.split('.') - package_components.reverse() # find the last occurrence of 'models' - try: - app_label_index = package_components.index(MODELS_MODULE_NAME) + 1 - except ValueError: - app_label_index = 1 - kwargs = {"app_label": package_components[app_label_index]} else: kwargs = {} |
