From 3918eeb9fde03a2ad1941bce022615fff8eae34d Mon Sep 17 00:00:00 2001
From: Bouke Haarsma <bouke@webatoom.nl>
Date: Tue, 15 Oct 2013 17:24:35 +0200
Subject: [PATCH] Fixed #7551 -- Made GFK allow None init argument.

Thanks SamBull for the report.
---
 django/contrib/contenttypes/generic.py |  8 ++++++--
 tests/generic_relations/models.py      |  7 +++++++
 tests/generic_relations/tests.py       | 17 ++++++++++++++++-
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py
index 51eed3f28b..241f497590 100644
--- a/django/contrib/contenttypes/generic.py
+++ b/django/contrib/contenttypes/generic.py
@@ -59,8 +59,12 @@ class GenericForeignKey(six.with_metaclass(RenameGenericForeignKeyMethods)):
         """
         if self.name in kwargs:
             value = kwargs.pop(self.name)
-            kwargs[self.ct_field] = self.get_content_type(obj=value)
-            kwargs[self.fk_field] = value._get_pk_val()
+            if value is not None:
+                kwargs[self.ct_field] = self.get_content_type(obj=value)
+                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):
         if obj is not None:
diff --git a/tests/generic_relations/models.py b/tests/generic_relations/models.py
index 79eb59fe47..859a17845e 100644
--- a/tests/generic_relations/models.py
+++ b/tests/generic_relations/models.py
@@ -137,3 +137,10 @@ class ConcreteRelatedModel(models.Model):
 class ProxyRelatedModel(ConcreteRelatedModel):
     class Meta:
         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()
diff --git a/tests/generic_relations/tests.py b/tests/generic_relations/tests.py
index dde00ccc8a..6f3f267c5f 100644
--- a/tests/generic_relations/tests.py
+++ b/tests/generic_relations/tests.py
@@ -4,11 +4,12 @@ from django import forms
 from django.contrib.contenttypes.generic import generic_inlineformset_factory
 from django.contrib.contenttypes.models import ContentType
 from django.test import TestCase
+from django.utils import six
 
 from .models import (TaggedItem, ValuableTaggedItem, Comparison, Animal,
                      Vegetable, Mineral, Gecko, Rock, ManualPK,
                      ForProxyModelModel, ForConcreteModelModel,
-                     ProxyRelatedModel, ConcreteRelatedModel)
+                     ProxyRelatedModel, ConcreteRelatedModel, AllowsNullGFK)
 
 
 class GenericRelationsTests(TestCase):
@@ -440,3 +441,17 @@ class ProxyRelatedModelTest(TestCase):
         newrel.bases = [base]
         newrel = ConcreteRelatedModel.objects.get(pk=newrel.pk)
         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)