Fixed #23615 -- Validate that a Model instance's "check" attribute is a method.

The "check" name is a reserved word used by Django's check framework,
and cannot be redefined as something else other than a method, or the check
framework will raise an error.

This change amends the django.core.checks.model_check.check_all_models()
function, so that it verifies that a model instance's attribute "check"
is actually a method. This new check is assigned the id "models.E020".
This commit is contained in:
Rigel Di Scala 2014-10-14 14:10:27 +01:00 committed by Loic Bistuer
parent 157f9cf240
commit a5c77417a6
4 changed files with 83 additions and 10 deletions

View file

@ -8,11 +8,13 @@ from django.apps import apps
from django.conf import settings
from django.core import checks
from django.core.checks import Error, Warning
from django.core.checks.model_checks import check_all_models
from django.core.checks.registry import CheckRegistry
from django.core.checks.compatibility.django_1_6_0 import check_1_6_compatibility
from django.core.checks.compatibility.django_1_7_0 import check_1_7_compatibility
from django.core.management.base import CommandError
from django.core.management import call_command
from django.db import models
from django.db.models.fields import NOT_PROVIDED
from django.test import TestCase
from django.test.utils import override_settings, override_system_checks
@ -327,3 +329,56 @@ class SilencingCheckTests(TestCase):
self.assertEqual(out.getvalue(), 'System check identified no issues (1 silenced).\n')
self.assertEqual(err.getvalue(), '')
class CheckFrameworkReservedNamesTests(TestCase):
def setUp(self):
self.current_models = apps.all_models[__package__]
self.saved_models = set(self.current_models)
def tearDown(self):
for model in (set(self.current_models) - self.saved_models):
del self.current_models[model]
apps.clear_cache()
@override_settings(SILENCED_SYSTEM_CHECKS=['models.E020'])
def test_model_check_method_not_shadowed(self):
class ModelWithAttributeCalledCheck(models.Model):
check = 42
class ModelWithFieldCalledCheck(models.Model):
check = models.IntegerField()
class ModelWithRelatedManagerCalledCheck(models.Model):
pass
class ModelWithDescriptorCalledCheck(models.Model):
check = models.ForeignKey(ModelWithRelatedManagerCalledCheck)
article = models.ForeignKey(ModelWithRelatedManagerCalledCheck, related_name='check')
expected = [
Error(
"The 'ModelWithAttributeCalledCheck.check()' class method is "
"currently overridden by 42.",
hint=None,
obj=ModelWithAttributeCalledCheck,
id='models.E020'
),
Error(
"The 'ModelWithRelatedManagerCalledCheck.check()' class method is "
"currently overridden by %r." % ModelWithRelatedManagerCalledCheck.check,
hint=None,
obj=ModelWithRelatedManagerCalledCheck,
id='models.E020'
),
Error(
"The 'ModelWithDescriptorCalledCheck.check()' class method is "
"currently overridden by %r." % ModelWithDescriptorCalledCheck.check,
hint=None,
obj=ModelWithDescriptorCalledCheck,
id='models.E020'
),
]
self.assertEqual(check_all_models(), expected)