Fixed #22690 -- Added a check for proxy models containing fields.
Removed the FieldError raised by ModelBase.__new__ in this case.
This commit is contained in:
parent
5046c110cf
commit
ce993efda8
|
@ -194,9 +194,6 @@ class ModelBase(type):
|
||||||
base = parent
|
base = parent
|
||||||
if base is None:
|
if base is None:
|
||||||
raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
|
raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
|
||||||
if (new_class._meta.local_fields or
|
|
||||||
new_class._meta.local_many_to_many):
|
|
||||||
raise FieldError("Proxy model '%s' contains model fields." % name)
|
|
||||||
new_class._meta.setup_proxy(base)
|
new_class._meta.setup_proxy(base)
|
||||||
new_class._meta.concrete_model = base._meta.concrete_model
|
new_class._meta.concrete_model = base._meta.concrete_model
|
||||||
else:
|
else:
|
||||||
|
@ -1047,6 +1044,7 @@ class Model(six.with_metaclass(ModelBase)):
|
||||||
def check(cls, **kwargs):
|
def check(cls, **kwargs):
|
||||||
errors = []
|
errors = []
|
||||||
errors.extend(cls._check_swappable())
|
errors.extend(cls._check_swappable())
|
||||||
|
errors.extend(cls._check_model())
|
||||||
errors.extend(cls._check_managers(**kwargs))
|
errors.extend(cls._check_managers(**kwargs))
|
||||||
if not cls._meta.swapped:
|
if not cls._meta.swapped:
|
||||||
errors.extend(cls._check_fields(**kwargs))
|
errors.extend(cls._check_fields(**kwargs))
|
||||||
|
@ -1094,6 +1092,21 @@ class Model(six.with_metaclass(ModelBase)):
|
||||||
)
|
)
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _check_model(cls):
|
||||||
|
errors = []
|
||||||
|
if cls._meta.proxy:
|
||||||
|
if cls._meta.local_fields or cls._meta.local_many_to_many:
|
||||||
|
errors.append(
|
||||||
|
checks.Error(
|
||||||
|
"Proxy model '%s' contains model fields." % cls.__name__,
|
||||||
|
hint=None,
|
||||||
|
obj=None,
|
||||||
|
id='models.E017',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return errors
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _check_managers(cls, **kwargs):
|
def _check_managers(cls, **kwargs):
|
||||||
""" Perform all manager checks. """
|
""" Perform all manager checks. """
|
||||||
|
|
|
@ -45,6 +45,7 @@ Models
|
||||||
* **models.E014**: ``ordering`` must be a tuple or list (even if you want to order by only one field).
|
* **models.E014**: ``ordering`` must be a tuple or list (even if you want to order by only one field).
|
||||||
* **models.E015**: ``ordering`` refers to the non-existent field ``<field name>``.
|
* **models.E015**: ``ordering`` refers to the non-existent field ``<field name>``.
|
||||||
* **models.E016**: ``index_together/unique_together`` refers to field ``<field_name>`` which is not local to model ``<model>``.
|
* **models.E016**: ``index_together/unique_together`` refers to field ``<field_name>`` which is not local to model ``<model>``.
|
||||||
|
* **models.E017**: Proxy model ``<model>`` contains model fields.
|
||||||
|
|
||||||
Fields
|
Fields
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.apps import apps
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core import management
|
from django.core import management
|
||||||
from django.core.exceptions import FieldError
|
from django.core import checks
|
||||||
from django.db import models, DEFAULT_DB_ALIAS
|
from django.db import models, DEFAULT_DB_ALIAS
|
||||||
from django.db.models import signals
|
from django.db.models import signals
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
|
@ -143,13 +143,25 @@ class ProxyModelTests(TestCase):
|
||||||
self.assertRaises(TypeError, build_no_base_classes)
|
self.assertRaises(TypeError, build_no_base_classes)
|
||||||
|
|
||||||
def test_new_fields(self):
|
def test_new_fields(self):
|
||||||
def build_new_fields():
|
class NoNewFields(Person):
|
||||||
class NoNewFields(Person):
|
newfield = models.BooleanField()
|
||||||
newfield = models.BooleanField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
proxy = True
|
proxy = True
|
||||||
self.assertRaises(FieldError, build_new_fields)
|
# don't register this model in the app_cache for the current app,
|
||||||
|
# otherwise the check fails when other tests are being run.
|
||||||
|
app_label = 'no_such_app'
|
||||||
|
|
||||||
|
errors = NoNewFields.check()
|
||||||
|
expected = [
|
||||||
|
checks.Error(
|
||||||
|
"Proxy model 'NoNewFields' contains model fields.",
|
||||||
|
hint=None,
|
||||||
|
obj=None,
|
||||||
|
id='models.E017',
|
||||||
|
)
|
||||||
|
]
|
||||||
|
self.assertEqual(errors, expected)
|
||||||
|
|
||||||
@override_settings(TEST_SWAPPABLE_MODEL='proxy_models.AlternateModel')
|
@override_settings(TEST_SWAPPABLE_MODEL='proxy_models.AlternateModel')
|
||||||
def test_swappable(self):
|
def test_swappable(self):
|
||||||
|
|
Loading…
Reference in New Issue