Fixed #7551 -- Made GFK allow None init argument.

Thanks SamBull for the report.
This commit is contained in:
Bouke Haarsma 2013-10-15 17:24:35 +02:00 committed by Tim Graham
parent 763ac8b642
commit 3918eeb9fd
3 changed files with 29 additions and 3 deletions

View File

@ -59,8 +59,12 @@ class GenericForeignKey(six.with_metaclass(RenameGenericForeignKeyMethods)):
""" """
if self.name in kwargs: if self.name in kwargs:
value = kwargs.pop(self.name) value = kwargs.pop(self.name)
if value is not None:
kwargs[self.ct_field] = self.get_content_type(obj=value) kwargs[self.ct_field] = self.get_content_type(obj=value)
kwargs[self.fk_field] = value._get_pk_val() kwargs[self.fk_field] = value._get_pk_val()
else:
kwargs[self.ct_field] = None
kwargs[self.fk_field] = None
def get_content_type(self, obj=None, id=None, using=None): def get_content_type(self, obj=None, id=None, using=None):
if obj is not None: if obj is not None:

View File

@ -137,3 +137,10 @@ class ConcreteRelatedModel(models.Model):
class ProxyRelatedModel(ConcreteRelatedModel): class ProxyRelatedModel(ConcreteRelatedModel):
class Meta: class Meta:
proxy = True proxy = True
# To test fix for #7551
class AllowsNullGFK(models.Model):
content_type = models.ForeignKey(ContentType, null=True)
object_id = models.PositiveIntegerField(null=True)
content_object = generic.GenericForeignKey()

View File

@ -4,11 +4,12 @@ from django import forms
from django.contrib.contenttypes.generic import generic_inlineformset_factory from django.contrib.contenttypes.generic import generic_inlineformset_factory
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import TestCase from django.test import TestCase
from django.utils import six
from .models import (TaggedItem, ValuableTaggedItem, Comparison, Animal, from .models import (TaggedItem, ValuableTaggedItem, Comparison, Animal,
Vegetable, Mineral, Gecko, Rock, ManualPK, Vegetable, Mineral, Gecko, Rock, ManualPK,
ForProxyModelModel, ForConcreteModelModel, ForProxyModelModel, ForConcreteModelModel,
ProxyRelatedModel, ConcreteRelatedModel) ProxyRelatedModel, ConcreteRelatedModel, AllowsNullGFK)
class GenericRelationsTests(TestCase): class GenericRelationsTests(TestCase):
@ -440,3 +441,17 @@ class ProxyRelatedModelTest(TestCase):
newrel.bases = [base] newrel.bases = [base]
newrel = ConcreteRelatedModel.objects.get(pk=newrel.pk) newrel = ConcreteRelatedModel.objects.get(pk=newrel.pk)
self.assertEqual(base, newrel.bases.get()) self.assertEqual(base, newrel.bases.get())
class TestInitWithNoneArgument(TestCase):
def test_none_not_allowed(self):
# TaggedItem requires a content_type, initializing with None should
# raise a ValueError.
with six.assertRaisesRegex(self, ValueError,
'Cannot assign None: "TaggedItem.content_type" does not allow null values'):
TaggedItem(content_object=None)
def test_none_allowed(self):
# AllowsNullGFK doesn't require a content_type, so None argument should
# also be allowed.
AllowsNullGFK(content_object=None)