mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	[1.8.x] Fixed #24287 -- Added friendly error if a model is in a models.py outside an installed app.
This commit is contained in:
		| @@ -2,34 +2,41 @@ from __future__ import unicode_literals | |||||||
|  |  | ||||||
| import copy | import copy | ||||||
| import inspect | import inspect | ||||||
| from itertools import chain |  | ||||||
| import sys | import sys | ||||||
| import warnings | import warnings | ||||||
|  | from itertools import chain | ||||||
|  |  | ||||||
| from django.apps import apps | from django.apps import apps | ||||||
| from django.apps.config import MODELS_MODULE_NAME | from django.apps.config import MODELS_MODULE_NAME | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.core import checks | from django.core import checks | ||||||
| from django.core.exceptions import (FieldDoesNotExist, ObjectDoesNotExist, | from django.core.exceptions import ( | ||||||
|     MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS) |     NON_FIELD_ERRORS, FieldDoesNotExist, FieldError, ImproperlyConfigured, | ||||||
| from django.db import (router, connections, transaction, DatabaseError, |     MultipleObjectsReturned, ObjectDoesNotExist, ValidationError, | ||||||
|     DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY) | ) | ||||||
|  | from django.db import ( | ||||||
|  |     DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, DatabaseError, connections, | ||||||
|  |     router, transaction, | ||||||
|  | ) | ||||||
| from django.db.models import signals | from django.db.models import signals | ||||||
| from django.db.models.constants import LOOKUP_SEP | from django.db.models.constants import LOOKUP_SEP | ||||||
| from django.db.models.deletion import Collector | from django.db.models.deletion import Collector | ||||||
| from django.db.models.fields import AutoField | from django.db.models.fields import AutoField | ||||||
| from django.db.models.fields.related import (ForeignObjectRel, ManyToOneRel, | from django.db.models.fields.related import ( | ||||||
|     OneToOneField, add_lazy_relation) |     ForeignObjectRel, ManyToOneRel, OneToOneField, add_lazy_relation, | ||||||
|  | ) | ||||||
| from django.db.models.manager import ensure_default_manager | from django.db.models.manager import ensure_default_manager | ||||||
| from django.db.models.options import Options | from django.db.models.options import Options | ||||||
| from django.db.models.query import Q | from django.db.models.query import Q | ||||||
| from django.db.models.query_utils import DeferredAttribute, deferred_class_factory | from django.db.models.query_utils import ( | ||||||
|  |     DeferredAttribute, deferred_class_factory, | ||||||
|  | ) | ||||||
| from django.utils import six | from django.utils import six | ||||||
| from django.utils.deprecation import RemovedInDjango19Warning | from django.utils.deprecation import RemovedInDjango19Warning | ||||||
| from django.utils.encoding import force_str, force_text | from django.utils.encoding import force_str, force_text | ||||||
| from django.utils.functional import curry | from django.utils.functional import curry | ||||||
| from django.utils.six.moves import zip | from django.utils.six.moves import zip | ||||||
| from django.utils.text import get_text_list, capfirst | from django.utils.text import capfirst, get_text_list | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| from django.utils.version import get_version | from django.utils.version import get_version | ||||||
|  |  | ||||||
| @@ -115,8 +122,14 @@ class ModelBase(type): | |||||||
|                     app_label_index = package_components.index(MODELS_MODULE_NAME) + 1 |                     app_label_index = package_components.index(MODELS_MODULE_NAME) + 1 | ||||||
|                 except ValueError: |                 except ValueError: | ||||||
|                     app_label_index = 1 |                     app_label_index = 1 | ||||||
|                 kwargs = {"app_label": package_components[app_label_index]} |                 try: | ||||||
|  |                     kwargs = {"app_label": package_components[app_label_index]} | ||||||
|  |                 except IndexError: | ||||||
|  |                     raise ImproperlyConfigured( | ||||||
|  |                         'Unable to detect the app label for model "%s." ' | ||||||
|  |                         'Ensure that its module, "%s", is located inside an installed ' | ||||||
|  |                         'app.' % (new_class.__name__, model_module.__name__) | ||||||
|  |                     ) | ||||||
|             else: |             else: | ||||||
|                 kwargs = {"app_label": app_config.label} |                 kwargs = {"app_label": app_config.label} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| import os | import os | ||||||
|  | import sys | ||||||
|  |  | ||||||
| from django.apps import apps | from django.apps import apps | ||||||
|  | from django.core.exceptions import ImproperlyConfigured | ||||||
|  | from django.db import models | ||||||
| from django.test import TestCase | from django.test import TestCase | ||||||
| from django.test.utils import extend_sys_path | from django.test.utils import extend_sys_path | ||||||
| from django.utils._os import upath | from django.utils._os import upath | ||||||
| @@ -75,3 +78,26 @@ class GetModelsTest(TestCase): | |||||||
|         self.assertNotIn( |         self.assertNotIn( | ||||||
|             "NotInstalledModel", |             "NotInstalledModel", | ||||||
|             [m.__name__ for m in apps.get_models()]) |             [m.__name__ for m in apps.get_models()]) | ||||||
|  |  | ||||||
|  |     def test_exception_raised_if_model_declared_outside_app(self): | ||||||
|  |  | ||||||
|  |         class FakeModule(models.Model): | ||||||
|  |             __name__ = str("models_that_do_not_live_in_an_app") | ||||||
|  |  | ||||||
|  |         sys.modules['models_not_in_app'] = FakeModule | ||||||
|  |  | ||||||
|  |         def declare_model_outside_app(): | ||||||
|  |             models.base.ModelBase.__new__( | ||||||
|  |                 models.base.ModelBase, | ||||||
|  |                 str('Outsider'), | ||||||
|  |                 (models.Model,), | ||||||
|  |                 {'__module__': 'models_not_in_app'}) | ||||||
|  |  | ||||||
|  |         msg = ( | ||||||
|  |             'Unable to detect the app label for model "Outsider." ' | ||||||
|  |             'Ensure that its module, "models_that_do_not_live_in_an_app", ' | ||||||
|  |             'is located inside an installed app.' | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         with self.assertRaisesMessage(ImproperlyConfigured, msg): | ||||||
|  |             declare_model_outside_app() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user