summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig de Stigter <craig.destigter@koordinates.com>2014-05-29 10:26:57 +1200
committerTim Graham <timograham@gmail.com>2014-06-02 09:32:38 -0400
commitce993efda876b19569267badb6af5fd0e80cdee3 (patch)
treef5c4c8be1dc0ff7dd02ed52c4b856423c4bb00d8
parent5046c110cfbf5e867fec47c8c68677a76c9e1b68 (diff)
Fixed #22690 -- Added a check for proxy models containing fields.
Removed the FieldError raised by ModelBase.__new__ in this case.
-rw-r--r--django/db/models/base.py19
-rw-r--r--docs/ref/checks.txt1
-rw-r--r--tests/proxy_models/tests.py26
3 files changed, 36 insertions, 10 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index b223764879..11dcb5ba3e 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -194,9 +194,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:
@@ -1047,6 +1044,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))
@@ -1095,6 +1093,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. """
diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt
index 8cdeb1df91..65f3d95453 100644
--- a/docs/ref/checks.txt
+++ b/docs/ref/checks.txt
@@ -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.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.E017**: Proxy model ``<model>`` contains model fields.
Fields
~~~~~~
diff --git a/tests/proxy_models/tests.py b/tests/proxy_models/tests.py
index 0052ff4630..7cb5bdf441 100644
--- a/tests/proxy_models/tests.py
+++ b/tests/proxy_models/tests.py
@@ -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):