Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit b6ec268e23c5b8e90ed3c3db3e220deca6eee8cc 1 parent 0324151
Ramiro Morales authored November 14, 2010
13  django/core/management/validation.py
... ...
@@ -1,7 +1,14 @@
1 1
 import sys
  2
+
  3
+from django.contrib.contenttypes.generic import GenericForeignKey, GenericRelation
2 4
 from django.core.management.color import color_style
3 5
 from django.utils.itercompat import is_iterable
4 6
 
  7
+try:
  8
+    any
  9
+except NameError:
  10
+    from django.utils.itercompat import any
  11
+
5 12
 class ModelErrorCollection:
6 13
     def __init__(self, outfile=sys.stdout):
7 14
         self.errors = []
@@ -224,6 +231,12 @@ def get_validation_errors(outfile, app=None):
224 231
                 e.add(opts, "'%s' specifies an m2m relation through model %s, "
225 232
                     "which has not been installed" % (f.name, f.rel.through)
226 233
                 )
  234
+            elif isinstance(f, GenericRelation):
  235
+                if not any([isinstance(vfield, GenericForeignKey) for vfield in f.rel.to._meta.virtual_fields]):
  236
+                    e.add(opts, "Model '%s' must have a GenericForeignKey in "
  237
+                        "order to create a GenericRelation that points to it."
  238
+                        % f.rel.to.__name__
  239
+                    )
227 240
 
228 241
             rel_opts = f.rel.to._meta
229 242
             rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
6  django/utils/itercompat.py
@@ -37,3 +37,9 @@ def all(iterable):
37 37
         if not item:
38 38
             return False
39 39
     return True
  40
+
  41
+def any(iterable):
  42
+    for item in iterable:
  43
+        if item:
  44
+            return True
  45
+    return False
16  tests/modeltests/invalid_models/models.py
@@ -4,6 +4,7 @@
4 4
 This example exists purely to point out errors in models.
5 5
 """
6 6
 
  7
+from django.contrib.contenttypes import generic
7 8
 from django.db import models
8 9
 
9 10
 class FieldErrors(models.Model):
@@ -216,6 +217,20 @@ class InvalidSetNull(models.Model):
216 217
 class InvalidSetDefault(models.Model):
217 218
     fk = models.ForeignKey('self', on_delete=models.SET_DEFAULT)
218 219
 
  220
+class Tag(models.Model):
  221
+   name = models.CharField("name", max_length=20)
  222
+
  223
+class TaggedObject(models.Model):
  224
+   object_id = models.PositiveIntegerField("Object ID")
  225
+   tag = models.ForeignKey(Tag)
  226
+   content_object = generic.GenericForeignKey()
  227
+
  228
+class UserTaggedObject(models.Model):
  229
+   object_tag = models.ForeignKey(TaggedObject)
  230
+
  231
+class ArticleAttachment(models.Model):
  232
+   tags = generic.GenericRelation(TaggedObject)
  233
+   user_tags = generic.GenericRelation(UserTaggedObject)
219 234
 
220 235
 model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute that is a positive integer.
221 236
 invalid_models.fielderrors: "charfield2": CharFields require a "max_length" attribute that is a positive integer.
@@ -324,4 +339,5 @@ class InvalidSetDefault(models.Model):
324 339
 invalid_models.nonexistingorderingwithsingleunderscore: "ordering" refers to "does_not_exist", a field that doesn't exist.
325 340
 invalid_models.invalidsetnull: 'fk' specifies on_delete=SET_NULL, but cannot be null.
326 341
 invalid_models.invalidsetdefault: 'fk' specifies on_delete=SET_DEFAULT, but has no default value.
  342
+invalid_models.articleattachment: Model 'UserTaggedObject' must have a GenericForeignKey in order to create a GenericRelation that points to it.
327 343
 """

0 notes on commit b6ec268

Please sign in to comment.
Something went wrong with that request. Please try again.