Cleanup of contrib.contenttypes check messages.

This commit is contained in:
Russell Keith-Magee 2014-03-03 14:19:06 +08:00
parent 84207b6134
commit 57e08aa232
2 changed files with 70 additions and 159 deletions

View File

@ -55,24 +55,16 @@ class GenericForeignKey(six.with_metaclass(RenameGenericForeignKeyMethods)):
def check(self, **kwargs): def check(self, **kwargs):
errors = [] errors = []
errors.extend(self._check_content_type_field())
errors.extend(self._check_object_id_field())
errors.extend(self._check_field_name()) errors.extend(self._check_field_name())
errors.extend(self._check_object_id_field())
errors.extend(self._check_content_type_field())
return errors return errors
def _check_content_type_field(self): def _check_field_name(self):
return _check_content_type_field( if self.name.endswith("_"):
model=self.model,
field_name=self.ct_field,
checked_object=self)
def _check_object_id_field(self):
try:
self.model._meta.get_field(self.fk_field)
except FieldDoesNotExist:
return [ return [
checks.Error( checks.Error(
'The field refers to "%s" field which is missing.' % self.fk_field, 'Field names must not end with an underscore.',
hint=None, hint=None,
obj=self, obj=self,
id='contenttypes.E001', id='contenttypes.E001',
@ -81,11 +73,13 @@ class GenericForeignKey(six.with_metaclass(RenameGenericForeignKeyMethods)):
else: else:
return [] return []
def _check_field_name(self): def _check_object_id_field(self):
if self.name.endswith("_"): try:
self.model._meta.get_field(self.fk_field)
except FieldDoesNotExist:
return [ return [
checks.Error( checks.Error(
'Field names must not end with underscores.', "The GenericForeignKey object ID references the non-existent field '%s'." % self.fk_field,
hint=None, hint=None,
obj=self, obj=self,
id='contenttypes.E002', id='contenttypes.E002',
@ -94,6 +88,49 @@ class GenericForeignKey(six.with_metaclass(RenameGenericForeignKeyMethods)):
else: else:
return [] return []
def _check_content_type_field(self):
""" Check if field named `field_name` in model `model` exists and is
valid content_type field (is a ForeignKey to ContentType). """
try:
field = self.model._meta.get_field(self.ct_field)
except FieldDoesNotExist:
return [
checks.Error(
"The GenericForeignKey content type references the non-existent field '%s.%s'." % (
self.model._meta.object_name, self.ct_field
),
hint=None,
obj=self,
id='contenttypes.E003',
)
]
else:
if not isinstance(field, models.ForeignKey):
return [
checks.Error(
"'%s.%s' is not a ForeignKey." % (
self.model._meta.object_name, self.ct_field
),
hint="GenericForeignKeys must use a ForeignKey to 'contenttypes.ContentType' as the 'content_type' field.",
obj=self,
id='contenttypes.E004',
)
]
elif field.rel.to != ContentType:
return [
checks.Error(
"'%s.%s' is not a ForeignKey to 'contenttypes.ContentType'." % (
self.model._meta.object_name, self.ct_field
),
hint="GenericForeignKeys must use a ForeignKey to 'contenttypes.ContentType' as the 'content_type' field.",
obj=self,
id='contenttypes.E005',
)
]
else:
return []
def instance_pre_init(self, signal, sender, args, kwargs, **_kwargs): def instance_pre_init(self, signal, sender, args, kwargs, **_kwargs):
""" """
Handles initializing an object with the generic FK instead of Handles initializing an object with the generic FK instead of
@ -228,43 +265,9 @@ class GenericRelation(ForeignObject):
def check(self, **kwargs): def check(self, **kwargs):
errors = super(GenericRelation, self).check(**kwargs) errors = super(GenericRelation, self).check(**kwargs)
errors.extend(self._check_content_type_field())
errors.extend(self._check_object_id_field())
errors.extend(self._check_generic_foreign_key_existence()) errors.extend(self._check_generic_foreign_key_existence())
return errors return errors
def _check_content_type_field(self):
target = self.rel.to
if isinstance(target, ModelBase):
return _check_content_type_field(
model=target,
field_name=self.content_type_field_name,
checked_object=self)
else:
return []
def _check_object_id_field(self):
target = self.rel.to
if isinstance(target, ModelBase):
opts = target._meta
try:
opts.get_field(self.object_id_field_name)
except FieldDoesNotExist:
return [
checks.Error(
'The field refers to %s.%s field which is missing.' % (
opts.object_name, self.object_id_field_name
),
hint=None,
obj=self,
id='contenttypes.E003',
)
]
else:
return []
else:
return []
def _check_generic_foreign_key_existence(self): def _check_generic_foreign_key_existence(self):
target = self.rel.to target = self.rel.to
if isinstance(target, ModelBase): if isinstance(target, ModelBase):
@ -280,8 +283,8 @@ class GenericRelation(ForeignObject):
else: else:
return [ return [
checks.Warning( checks.Warning(
('The field defines a generic relation with the model ' ("The GenericRelation defines a relation with the model "
'%s.%s, but the model lacks GenericForeignKey.') % ( "'%s.%s', but that model does not have a GenericForeignKey.") % (
target._meta.app_label, target._meta.object_name target._meta.app_label, target._meta.object_name
), ),
hint=None, hint=None,
@ -359,54 +362,6 @@ class GenericRelation(ForeignObject):
}) })
def _check_content_type_field(model, field_name, checked_object):
""" Check if field named `field_name` in model `model` exists and is
valid content_type field (is a ForeignKey to ContentType). """
try:
field = model._meta.get_field(field_name)
except FieldDoesNotExist:
return [
checks.Error(
'The field refers to %s.%s field which is missing.' % (
model._meta.object_name, field_name
),
hint=None,
obj=checked_object,
id='contenttypes.E005',
)
]
else:
if not isinstance(field, models.ForeignKey):
return [
checks.Error(
('"%s" field is used by a %s '
'as content type field and therefore it must be '
'a ForeignKey.') % (
field_name, checked_object.__class__.__name__
),
hint=None,
obj=checked_object,
id='contenttypes.E006',
)
]
elif field.rel.to != ContentType:
return [
checks.Error(
('"%s" field is used by a %s '
'as content type field and therefore it must be '
'a ForeignKey to ContentType.') % (
field_name, checked_object.__class__.__name__
),
hint=None,
obj=checked_object,
id='contenttypes.E007',
)
]
else:
return []
class ReverseGenericRelatedObjectsDescriptor(object): class ReverseGenericRelatedObjectsDescriptor(object):
""" """
This class provides the functionality that makes the related-object This class provides the functionality that makes the related-object

View File

@ -106,10 +106,10 @@ class GenericForeignKeyTests(IsolatedModelsTestCase):
errors = TaggedItem.content_object.check() errors = TaggedItem.content_object.check()
expected = [ expected = [
checks.Error( checks.Error(
'The field refers to TaggedItem.content_type field which is missing.', "The GenericForeignKey content type references the non-existent field 'TaggedItem.content_type'.",
hint=None, hint=None,
obj=TaggedItem.content_object, obj=TaggedItem.content_object,
id='contenttypes.E005', id='contenttypes.E003',
) )
] ]
self.assertEqual(errors, expected) self.assertEqual(errors, expected)
@ -124,12 +124,10 @@ class GenericForeignKeyTests(IsolatedModelsTestCase):
errors = Model.content_object.check() errors = Model.content_object.check()
expected = [ expected = [
checks.Error( checks.Error(
('"content_type" field is used by a GenericForeignKey ' "'Model.content_type' is not a ForeignKey.",
'as content type field and therefore it must be ' hint="GenericForeignKeys must use a ForeignKey to 'contenttypes.ContentType' as the 'content_type' field.",
'a ForeignKey.'),
hint=None,
obj=Model.content_object, obj=Model.content_object,
id='contenttypes.E006', id='contenttypes.E004',
) )
] ]
self.assertEqual(errors, expected) self.assertEqual(errors, expected)
@ -144,12 +142,10 @@ class GenericForeignKeyTests(IsolatedModelsTestCase):
errors = Model.content_object.check() errors = Model.content_object.check()
expected = [ expected = [
checks.Error( checks.Error(
('"content_type" field is used by a GenericForeignKey ' "'Model.content_type' is not a ForeignKey to 'contenttypes.ContentType'.",
'as content type field and therefore it must be ' hint="GenericForeignKeys must use a ForeignKey to 'contenttypes.ContentType' as the 'content_type' field.",
'a ForeignKey to ContentType.'),
hint=None,
obj=Model.content_object, obj=Model.content_object,
id='contenttypes.E007', id='contenttypes.E005',
) )
] ]
self.assertEqual(errors, expected) self.assertEqual(errors, expected)
@ -163,10 +159,10 @@ class GenericForeignKeyTests(IsolatedModelsTestCase):
errors = TaggedItem.content_object.check() errors = TaggedItem.content_object.check()
expected = [ expected = [
checks.Error( checks.Error(
'The field refers to "object_id" field which is missing.', "The GenericForeignKey object ID references the non-existent field 'object_id'.",
hint=None, hint=None,
obj=TaggedItem.content_object, obj=TaggedItem.content_object,
id='contenttypes.E001', id='contenttypes.E002',
) )
] ]
self.assertEqual(errors, expected) self.assertEqual(errors, expected)
@ -181,10 +177,10 @@ class GenericForeignKeyTests(IsolatedModelsTestCase):
errors = Model.content_object_.check() errors = Model.content_object_.check()
expected = [ expected = [
checks.Error( checks.Error(
'Field names must not end with underscores.', 'Field names must not end with an underscore.',
hint=None, hint=None,
obj=Model.content_object_, obj=Model.content_object_,
id='contenttypes.E002', id='contenttypes.E001',
) )
] ]
self.assertEqual(errors, expected) self.assertEqual(errors, expected)
@ -259,46 +255,6 @@ class GenericRelationshipTests(IsolatedModelsTestCase):
errors = Model.rel.field.check() errors = Model.rel.field.check()
self.assertEqual(errors, []) self.assertEqual(errors, [])
def test_missing_content_type_field(self):
class TaggedItem(models.Model):
# no content_type field
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
class Bookmark(models.Model):
tags = GenericRelation('TaggedItem')
errors = Bookmark.tags.field.check()
expected = [
checks.Error(
'The field refers to TaggedItem.content_type field which is missing.',
hint=None,
obj=Bookmark.tags.field,
id='contenttypes.E005',
)
]
self.assertEqual(errors, expected)
def test_missing_object_id_field(self):
class TaggedItem(models.Model):
content_type = models.ForeignKey(ContentType)
# missing object_id field
content_object = GenericForeignKey()
class Bookmark(models.Model):
tags = GenericRelation('TaggedItem')
errors = Bookmark.tags.field.check()
expected = [
checks.Error(
'The field refers to TaggedItem.object_id field which is missing.',
hint=None,
obj=Bookmark.tags.field,
id='contenttypes.E003',
)
]
self.assertEqual(errors, expected)
def test_missing_generic_foreign_key(self): def test_missing_generic_foreign_key(self):
class TaggedItem(models.Model): class TaggedItem(models.Model):
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType)
@ -310,9 +266,9 @@ class GenericRelationshipTests(IsolatedModelsTestCase):
errors = Bookmark.tags.field.check() errors = Bookmark.tags.field.check()
expected = [ expected = [
checks.Warning( checks.Warning(
('The field defines a generic relation with the model ' ("The GenericRelation defines a relation with the model "
'contenttypes_tests.TaggedItem, but the model lacks ' "'contenttypes_tests.TaggedItem', but that model does not have a "
'GenericForeignKey.'), "GenericForeignKey."),
hint=None, hint=None,
obj=Bookmark.tags.field, obj=Bookmark.tags.field,
id='contenttypes.E004', id='contenttypes.E004',