Loading django/db/models/base.py +15 −3 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ from django.db.models.query_utils import DeferredAttribute, deferred_class_facto from django.db.models.deletion import Collector from django.db.models.options import Options from django.db.models import signals from django.db.models.loading import register_models, get_model from django.db.models.loading import register_models, get_model, MODELS_MODULE_NAME from django.utils.translation import ugettext_lazy as _ from django.utils.functional import curry from django.utils.encoding import force_str, force_text Loading Loading @@ -86,10 +86,22 @@ class ModelBase(type): base_meta = getattr(new_class, '_meta', None) if getattr(meta, 'app_label', None) is None: # Figure out the app_label by looking one level up. # 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__] kwargs = {"app_label": model_module.__name__.split('.')[-2]} 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 = {} Loading django/db/models/loading.py +4 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ import os __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models', 'load_app', 'app_cache_ready') MODELS_MODULE_NAME = 'models' class UnavailableApp(Exception): pass Loading Loading @@ -98,12 +100,12 @@ class AppCache(object): self.nesting_level += 1 app_module = import_module(app_name) try: models = import_module('.models', app_name) models = import_module('.' + MODELS_MODULE_NAME, app_name) except ImportError: self.nesting_level -= 1 # If the app doesn't have a models module, we can just ignore the # ImportError and return no models for it. if not module_has_submodule(app_module, 'models'): if not module_has_submodule(app_module, MODELS_MODULE_NAME): return None # But if the app does have a models module, we need to figure out # whether to suppress or propagate the error. If can_postpone is Loading docs/ref/models/options.txt +8 −3 Original line number Diff line number Diff line Loading @@ -24,12 +24,17 @@ Available ``Meta`` options .. attribute:: Options.app_label If a model exists outside of the standard :file:`models.py` (for instance, if the app's models are in submodules of ``myapp.models``), the model must define which app it is part of:: If a model exists outside of the standard locations (:file:`models.py` or a ``models`` package in an app), the model must define which app it is part of:: app_label = 'myapp' .. versionadded:: 1.7 ``app_label`` is no longer required for models that are defined in a ``models`` package within an app. ``db_table`` ------------ Loading docs/releases/1.7.txt +3 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,9 @@ Minor features * The :meth:`QuerySet.update_or_create() <django.db.models.query.QuerySet.update_or_create>` method was added. * :attr:`~django.db.models.Options.app_label` is no longer required for models that are defined in a ``models`` package within an app. Backwards incompatible changes in 1.7 ===================================== Loading tests/model_package/models/article.py +0 −3 Original line number Diff line number Diff line Loading @@ -6,6 +6,3 @@ class Article(models.Model): sites = models.ManyToManyField(Site) headline = models.CharField(max_length=100) publications = models.ManyToManyField("model_package.Publication", null=True, blank=True,) class Meta: app_label = 'model_package' Loading
django/db/models/base.py +15 −3 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ from django.db.models.query_utils import DeferredAttribute, deferred_class_facto from django.db.models.deletion import Collector from django.db.models.options import Options from django.db.models import signals from django.db.models.loading import register_models, get_model from django.db.models.loading import register_models, get_model, MODELS_MODULE_NAME from django.utils.translation import ugettext_lazy as _ from django.utils.functional import curry from django.utils.encoding import force_str, force_text Loading Loading @@ -86,10 +86,22 @@ class ModelBase(type): base_meta = getattr(new_class, '_meta', None) if getattr(meta, 'app_label', None) is None: # Figure out the app_label by looking one level up. # 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__] kwargs = {"app_label": model_module.__name__.split('.')[-2]} 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 = {} Loading
django/db/models/loading.py +4 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ import os __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models', 'load_app', 'app_cache_ready') MODELS_MODULE_NAME = 'models' class UnavailableApp(Exception): pass Loading Loading @@ -98,12 +100,12 @@ class AppCache(object): self.nesting_level += 1 app_module = import_module(app_name) try: models = import_module('.models', app_name) models = import_module('.' + MODELS_MODULE_NAME, app_name) except ImportError: self.nesting_level -= 1 # If the app doesn't have a models module, we can just ignore the # ImportError and return no models for it. if not module_has_submodule(app_module, 'models'): if not module_has_submodule(app_module, MODELS_MODULE_NAME): return None # But if the app does have a models module, we need to figure out # whether to suppress or propagate the error. If can_postpone is Loading
docs/ref/models/options.txt +8 −3 Original line number Diff line number Diff line Loading @@ -24,12 +24,17 @@ Available ``Meta`` options .. attribute:: Options.app_label If a model exists outside of the standard :file:`models.py` (for instance, if the app's models are in submodules of ``myapp.models``), the model must define which app it is part of:: If a model exists outside of the standard locations (:file:`models.py` or a ``models`` package in an app), the model must define which app it is part of:: app_label = 'myapp' .. versionadded:: 1.7 ``app_label`` is no longer required for models that are defined in a ``models`` package within an app. ``db_table`` ------------ Loading
docs/releases/1.7.txt +3 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,9 @@ Minor features * The :meth:`QuerySet.update_or_create() <django.db.models.query.QuerySet.update_or_create>` method was added. * :attr:`~django.db.models.Options.app_label` is no longer required for models that are defined in a ``models`` package within an app. Backwards incompatible changes in 1.7 ===================================== Loading
tests/model_package/models/article.py +0 −3 Original line number Diff line number Diff line Loading @@ -6,6 +6,3 @@ class Article(models.Model): sites = models.ManyToManyField(Site) headline = models.CharField(max_length=100) publications = models.ManyToManyField("model_package.Publication", null=True, blank=True,) class Meta: app_label = 'model_package'