From d847ddfe1d4475e768c547b17642d3ed0894d54e Mon Sep 17 00:00:00 2001 From: Loic Bistuer Date: Mon, 30 Sep 2013 10:21:21 +0700 Subject: [PATCH] Fixed #3871 -- Fixed regression introduced by 04a2a6b. Added do_not_call_in_templates=True attribute to RelatedManagers to prevent them from being called. Thanks jbg@ for the report. --- django/contrib/contenttypes/generic.py | 1 + django/db/models/fields/related.py | 2 ++ tests/managers_regress/models.py | 27 +++++++++++++++++++++++++- tests/managers_regress/tests.py | 21 +++++++++++++++++++- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py index f3d66eaf315..b34847b81d0 100644 --- a/django/contrib/contenttypes/generic.py +++ b/django/contrib/contenttypes/generic.py @@ -335,6 +335,7 @@ def create_generic_related_manager(superclass): object_id_field_name = self.object_id_field_name, prefetch_cache_name = self.prefetch_cache_name, ) + do_not_call_in_templates = True def get_queryset(self): try: diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 6c1e96ad8cf..6cd8d193f53 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -377,6 +377,7 @@ def create_foreign_related_manager(superclass, rel_field, rel_model): manager = getattr(self.model, kwargs.pop('manager')) manager_class = create_foreign_related_manager(manager.__class__, rel_field, rel_model) return manager_class(self.instance) + do_not_call_in_templates = True def get_queryset(self): try: @@ -545,6 +546,7 @@ def create_many_related_manager(superclass, rel): through=self.through, prefetch_cache_name=self.prefetch_cache_name, ) + do_not_call_in_templates = True def get_queryset(self): try: diff --git a/tests/managers_regress/models.py b/tests/managers_regress/models.py index d8dd22ec9a1..80b25a72fc0 100644 --- a/tests/managers_regress/models.py +++ b/tests/managers_regress/models.py @@ -3,7 +3,9 @@ Various edge-cases for model managers. """ from django.db import models -from django.utils.encoding import python_2_unicode_compatible +from django.contrib.contenttypes import generic +from django.contrib.contenttypes.models import ContentType +from django.utils.encoding import python_2_unicode_compatible, force_text class OnlyFred(models.Manager): @@ -119,3 +121,26 @@ class Child6(Child4): # Will not inherit default manager from parent. class Child7(Parent): pass + + +# RelatedManagers +@python_2_unicode_compatible +class RelatedModel(models.Model): + test_gfk = generic.GenericRelation('RelationModel', content_type_field='gfk_ctype', object_id_field='gfk_id') + + def __str__(self): + return force_text(self.pk) + + +@python_2_unicode_compatible +class RelationModel(models.Model): + fk = models.ForeignKey(RelatedModel, related_name='test_fk') + + m2m = models.ManyToManyField(RelatedModel, related_name='test_m2m') + + gfk_ctype = models.ForeignKey(ContentType) + gfk_id = models.IntegerField() + gfk = generic.GenericForeignKey(ct_field='gfk_ctype', fk_field='gfk_id') + + def __str__(self): + return force_text(self.pk) diff --git a/tests/managers_regress/tests.py b/tests/managers_regress/tests.py index e5dce531229..333ffc3b954 100644 --- a/tests/managers_regress/tests.py +++ b/tests/managers_regress/tests.py @@ -4,8 +4,9 @@ import copy from django.conf import settings from django.db import models from django.db.models.loading import cache +from django.template import Context, Template from django.test import TestCase -from django.test.utils import override_settings +from django.utils.encoding import force_text from .models import ( Child1, @@ -18,6 +19,8 @@ from .models import ( AbstractBase1, AbstractBase2, AbstractBase3, + RelatedModel, + RelationModel, ) @@ -193,3 +196,19 @@ class ManagersRegressionTests(TestCase): del settings.TEST_SWAPPABLE_MODEL cache.app_models = old_app_models cache.app_store = old_app_store + + def test_regress_3871(self): + related = RelatedModel.objects.create() + + relation = RelationModel() + relation.fk = related + relation.gfk = related + relation.save() + relation.m2m.add(related) + + t = Template('{{ related.test_fk.all.0 }}{{ related.test_gfk.all.0 }}{{ related.test_m2m.all.0 }}') + + self.assertEqual( + t.render(Context({'related': related})), + ''.join([force_text(relation.pk)] * 3), + )