Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #13085 -- Don't fail on creation of model with GFK to a model w…

…ith __len__() returning zero.

Also, according to the comments on the ticket and its duplicates, added
tests execising saving an instance of a model with a GFK to:

* An unsaved object -- This actually doesn't generate the same failure
  but another ORM-level exception. The test verifies it's the case.

* An instance of a model with a __nonzero__() method thant returns False
  for it. This doesn't fail because that code path isn't executed.

* An instance of a model with a CharField PK and an empty value for it.
  This doesn't fail.
  • Loading branch information...
commit 04d9730b127c689b8eda01cbc913efa6e2eb230b 1 parent 2b91689
@ramiro ramiro authored
View
4 django/contrib/contenttypes/generic.py
@@ -43,7 +43,7 @@ def contribute_to_class(self, cls, name):
def instance_pre_init(self, signal, sender, args, kwargs, **_kwargs):
"""
- Handles initializing an object with the generic FK instaed of
+ Handles initializing an object with the generic FK instead of
content-type/object-id fields.
"""
if self.name in kwargs:
@@ -52,7 +52,7 @@ def instance_pre_init(self, signal, sender, args, kwargs, **_kwargs):
kwargs[self.fk_field] = value._get_pk_val()
def get_content_type(self, obj=None, id=None, using=None):
- if obj:
+ if obj is not None:
return ContentType.objects.db_manager(obj._state.db).get_for_model(obj)
elif id:
return ContentType.objects.db_manager(using).get_for_id(id)
View
31 tests/regressiontests/generic_relations_regress/models.py
@@ -91,3 +91,34 @@ class Company(models.Model):
def __str__(self):
return "Company: %s" % self.name
+
+# For testing #13085 fix, we also use Note model defined above
+class Developer(models.Model):
+ name = models.CharField(max_length=15)
+
+@python_2_unicode_compatible
+class Team(models.Model):
+ name = models.CharField(max_length=15)
+ members = models.ManyToManyField(Developer)
+
+ def __str__(self):
+ return "%s team" % self.name
+
+ def __len__(self):
+ return self.members.count()
+
+class Guild(models.Model):
+ name = models.CharField(max_length=15)
+ members = models.ManyToManyField(Developer)
+
+ def __nonzero__(self):
+ return self.members.count()
+
+class Tag(models.Model):
+ content_type = models.ForeignKey(ContentType, related_name='g_r_r_tags')
+ object_id = models.CharField(max_length=15)
+ content_object = generic.GenericForeignKey()
+ label = models.CharField(max_length=15)
+
+class Board(models.Model):
+ name = models.CharField(primary_key=True, max_length=15)
View
40 tests/regressiontests/generic_relations_regress/tests.py
@@ -1,8 +1,10 @@
from django.db.models import Q
+from django.db.utils import IntegrityError
from django.test import TestCase
from .models import (Address, Place, Restaurant, Link, CharLink, TextLink,
- Person, Contact, Note, Organization, OddRelation1, OddRelation2, Company)
+ Person, Contact, Note, Organization, OddRelation1, OddRelation2, Company,
+ Developer, Team, Guild, Tag, Board)
class GenericRelationTests(TestCase):
@@ -98,3 +100,39 @@ def count_places(place):
self.assertEqual(len(places), 2)
self.assertEqual(count_places(p1), 1)
self.assertEqual(count_places(p2), 1)
+
+ def test_target_model_is_unsaved(self):
+ """Test related to #13085"""
+ # Fails with another, ORM-level error
+ dev1 = Developer(name='Joe')
+ note = Note(note='Deserves promotion', content_object=dev1)
+ self.assertRaisesMessage(IntegrityError,
+ "generic_relations_regress_note.object_id may not be NULL",
+ note.save)
+
+ def test_target_model_len_zero(self):
+ """Test for #13085 -- __len__() returns 0"""
+ team1 = Team.objects.create(name='Backend devs')
+ try:
+ note = Note(note='Deserve a bonus', content_object=team1)
+ except Exception as e:
+ if issubclass(type(e), Exception) and str(e) == 'Impossible arguments to GFK.get_content_type!':
+ self.fail("Saving model with GenericForeignKey to model instance whose __len__ method returns 0 shouldn't fail.")
+ raise e
+ note.save()
+
+ def test_target_model_nonzero_false(self):
+ """Test related to #13085"""
+ # __nonzero__() returns False -- This actually doesn't currently fail.
+ # This test validates that
+ g1 = Guild.objects.create(name='First guild')
+ note = Note(note='Note for guild', content_object=g1)
+ note.save()
+
+ def test_gfk_to_model_with_empty_pk(self):
+ """Test related to #13085"""
+ # Saving model with GenericForeignKey to model instance with an
+ # empty CharField PK
+ b1 = Board.objects.create(name='')
+ tag = Tag(label='VP', content_object=b1)
+ tag.save()

0 comments on commit 04d9730

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