[1.7.x] Fixed #22690 -- Added a check for proxy models containing fields.
Removed the FieldError raised by ModelBase.__new__ in this case.
Backport of ce993efda8
from master
This commit is contained in:
parent
160fd6c7c1
commit
724e600872
|
@ -193,9 +193,6 @@ class ModelBase(type):
|
|||
base = parent
|
||||
if base is None:
|
||||
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.concrete_model = base._meta.concrete_model
|
||||
else:
|
||||
|
@ -1044,6 +1041,7 @@ class Model(six.with_metaclass(ModelBase)):
|
|||
def check(cls, **kwargs):
|
||||
errors = []
|
||||
errors.extend(cls._check_swappable())
|
||||
errors.extend(cls._check_model())
|
||||
errors.extend(cls._check_managers(**kwargs))
|
||||
if not cls._meta.swapped:
|
||||
errors.extend(cls._check_fields(**kwargs))
|
||||
|
@ -1091,6 +1089,21 @@ class Model(six.with_metaclass(ModelBase)):
|
|||
)
|
||||
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
|
||||
def _check_managers(cls, **kwargs):
|
||||
""" Perform all manager checks. """
|
||||
|
|
|
@ -44,6 +44,7 @@ Models
|
|||
* **models.E013**: ``index_together/unique_together`` refers to a ManyToManyField ``<field name>``, but ManyToManyFields are not supported for that option.
|
||||
* **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.E017**: Proxy model ``<model>`` contains model fields.
|
||||
|
||||
Fields
|
||||
~~~~~~
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.apps import apps
|
|||
from django.contrib import admin
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
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.models import signals
|
||||
from django.test import TestCase, override_settings
|
||||
|
@ -143,13 +143,25 @@ class ProxyModelTests(TestCase):
|
|||
self.assertRaises(TypeError, build_no_base_classes)
|
||||
|
||||
def test_new_fields(self):
|
||||
def build_new_fields():
|
||||
class NoNewFields(Person):
|
||||
newfield = models.BooleanField()
|
||||
class NoNewFields(Person):
|
||||
newfield = models.BooleanField()
|
||||
|
||||
class Meta:
|
||||
proxy = True
|
||||
self.assertRaises(FieldError, build_new_fields)
|
||||
class Meta:
|
||||
proxy = True
|
||||
# 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')
|
||||
def test_swappable(self):
|
||||
|
|
Loading…
Reference in New Issue