summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamiro Morales <cramm0@gmail.com>2010-11-14 23:21:39 +0000
committerRamiro Morales <cramm0@gmail.com>2010-11-14 23:21:39 +0000
commitb6ec268e23c5b8e90ed3c3db3e220deca6eee8cc (patch)
treea52467603a553301145fbea48b1f0d5b5ba449fd
parent0324151bece5ab413250ada14428e41b6b59bf0b (diff)
Fiexed #3055 -- Validate that models target of a GenericRelation have a GenericForeignKey field.
Thanks jason for diagnosing the problem and Marcos Moyano for the patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@14563 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/core/management/validation.py13
-rw-r--r--django/utils/itercompat.py6
-rw-r--r--tests/modeltests/invalid_models/models.py16
3 files changed, 35 insertions, 0 deletions
diff --git a/django/core/management/validation.py b/django/core/management/validation.py
index 6baa189736..f78fa87b33 100644
--- a/django/core/management/validation.py
+++ b/django/core/management/validation.py
@@ -1,7 +1,14 @@
import sys
+
+from django.contrib.contenttypes.generic import GenericForeignKey, GenericRelation
from django.core.management.color import color_style
from django.utils.itercompat import is_iterable
+try:
+ any
+except NameError:
+ from django.utils.itercompat import any
+
class ModelErrorCollection:
def __init__(self, outfile=sys.stdout):
self.errors = []
@@ -224,6 +231,12 @@ def get_validation_errors(outfile, app=None):
e.add(opts, "'%s' specifies an m2m relation through model %s, "
"which has not been installed" % (f.name, f.rel.through)
)
+ elif isinstance(f, GenericRelation):
+ if not any([isinstance(vfield, GenericForeignKey) for vfield in f.rel.to._meta.virtual_fields]):
+ e.add(opts, "Model '%s' must have a GenericForeignKey in "
+ "order to create a GenericRelation that points to it."
+ % f.rel.to.__name__
+ )
rel_opts = f.rel.to._meta
rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
diff --git a/django/utils/itercompat.py b/django/utils/itercompat.py
index ab27c3ee01..d4ff2503c7 100644
--- a/django/utils/itercompat.py
+++ b/django/utils/itercompat.py
@@ -37,3 +37,9 @@ def all(iterable):
if not item:
return False
return True
+
+def any(iterable):
+ for item in iterable:
+ if item:
+ return True
+ return False
diff --git a/tests/modeltests/invalid_models/models.py b/tests/modeltests/invalid_models/models.py
index 6e2b579a33..2788aa077e 100644
--- a/tests/modeltests/invalid_models/models.py
+++ b/tests/modeltests/invalid_models/models.py
@@ -4,6 +4,7 @@
This example exists purely to point out errors in models.
"""
+from django.contrib.contenttypes import generic
from django.db import models
class FieldErrors(models.Model):
@@ -216,6 +217,20 @@ class InvalidSetNull(models.Model):
class InvalidSetDefault(models.Model):
fk = models.ForeignKey('self', on_delete=models.SET_DEFAULT)
+class Tag(models.Model):
+ name = models.CharField("name", max_length=20)
+
+class TaggedObject(models.Model):
+ object_id = models.PositiveIntegerField("Object ID")
+ tag = models.ForeignKey(Tag)
+ content_object = generic.GenericForeignKey()
+
+class UserTaggedObject(models.Model):
+ object_tag = models.ForeignKey(TaggedObject)
+
+class ArticleAttachment(models.Model):
+ tags = generic.GenericRelation(TaggedObject)
+ user_tags = generic.GenericRelation(UserTaggedObject)
model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute that is a positive integer.
invalid_models.fielderrors: "charfield2": CharFields require a "max_length" attribute that is a positive integer.
@@ -324,4 +339,5 @@ invalid_models.nonuniquefktarget2: Field 'bad' under model 'FKTarget' must have
invalid_models.nonexistingorderingwithsingleunderscore: "ordering" refers to "does_not_exist", a field that doesn't exist.
invalid_models.invalidsetnull: 'fk' specifies on_delete=SET_NULL, but cannot be null.
invalid_models.invalidsetdefault: 'fk' specifies on_delete=SET_DEFAULT, but has no default value.
+invalid_models.articleattachment: Model 'UserTaggedObject' must have a GenericForeignKey in order to create a GenericRelation that points to it.
"""