Commit 2f91f764 authored by Ramiro Morales's avatar Ramiro Morales
Browse files

[1.2.X] Fixed #3055 -- Validate that models target of a GenericRelation have a...

[1.2.X] Fixed #3055 -- Validate that models target of a GenericRelation have a GenericForeignKey field.

Thanks jason for diagnosing the problem and Marcos Moyano for the patch.

Backport of [14563] from trunk

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@14565 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent dc3b524f
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
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 = []
@@ -216,6 +223,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()
+6 −0
Original line number Diff line number Diff line
@@ -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
+17 −0
Original line number Diff line number Diff line
@@ -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):
@@ -210,6 +211,21 @@ class NonExistingOrderingWithSingleUnderscore(models.Model):
    class Meta:
        ordering = ("does_not_exist",)

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.
invalid_models.fielderrors: "charfield3": CharFields require a "max_length" attribute that is a positive integer.
@@ -315,4 +331,5 @@ invalid_models.uniquem2m: ManyToManyFields cannot be unique. Remove the unique
invalid_models.nonuniquefktarget1: Field 'bad' under model 'FKTarget' must have a unique=True constraint.
invalid_models.nonuniquefktarget2: Field 'bad' under model 'FKTarget' must have a unique=True constraint.
invalid_models.nonexistingorderingwithsingleunderscore: "ordering" refers to "does_not_exist", a field that doesn't exist.
invalid_models.articleattachment: Model 'UserTaggedObject' must have a GenericForeignKey in order to create a GenericRelation that points to it.
"""