1
0
mirror of https://github.com/django/django.git synced 2025-10-26 07:06:08 +00:00

Made it possible to change an application's label in its configuration.

Fixed #21683.
This commit is contained in:
Aymeric Augustin
2013-12-31 16:23:42 +01:00
parent 5dfec4e23b
commit c40209dcc0
8 changed files with 83 additions and 31 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 = {}