From 9500a21f82dd1b31f88d88e46bf8aa2411a701e9 Mon Sep 17 00:00:00 2001 From: trbs Date: Wed, 30 Aug 2017 21:17:05 +0200 Subject: [PATCH] fix error with .defer and child models that use the same parent When using .defer on a PolymorphicQuerySet with multiple childs that subclass from the same polymorphic parent model yield an error like: >>> Base.objects.defer('ModelY___field_y') Traceback (most recent call last): ... FieldDoesNotExist: ModelX has no field named 'field_y' --- polymorphic/query.py | 5 +++++ polymorphic/tests/__init__.py | 1 + polymorphic/tests/test_orm.py | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/polymorphic/query.py b/polymorphic/query.py index b780c37..454c526 100644 --- a/polymorphic/query.py +++ b/polymorphic/query.py @@ -8,6 +8,7 @@ import copy from collections import defaultdict from django.contrib.contenttypes.models import ContentType +from django.db.models import FieldDoesNotExist from django.db.models.query import ModelIterable, Q, QuerySet from django.utils import six @@ -392,6 +393,10 @@ class PolymorphicQuerySet(QuerySet): # now a superclass of real_concrete_class. Thus it's # sufficient to just use the field name. translated_field_name = field.rpartition('___')[-1] + try: + real_concrete_class._meta.get_field(translated_field_name) + except FieldDoesNotExist: + continue else: raise diff --git a/polymorphic/tests/__init__.py b/polymorphic/tests/__init__.py index 758233e..9e99441 100644 --- a/polymorphic/tests/__init__.py +++ b/polymorphic/tests/__init__.py @@ -82,6 +82,7 @@ class ModelShow2_plain(ModelShow1_plain): class Base(ShowFieldType, PolymorphicModel): field_b = models.CharField(max_length=10) + polymorphic_showfield_deferred = True class ModelX(Base): diff --git a/polymorphic/tests/test_orm.py b/polymorphic/tests/test_orm.py index 5f6186f..2736059 100644 --- a/polymorphic/tests/test_orm.py +++ b/polymorphic/tests/test_orm.py @@ -178,6 +178,23 @@ class PolymorphicTests(TestCase): '') + ModelX.objects.create(field_b="A1", field_x="A2") + ModelY.objects.create(field_b="B1", field_y="B2") + + objects_deferred = Base.objects.defer('ModelY___field_y') + self.assertEqual(repr(objects_deferred[0]), + '') + self.assertEqual(repr(objects_deferred[1]), + '') + + objects_only = Base.objects.only( + 'polymorphic_ctype', 'ModelY___field_y', 'ModelX___field_x', + ) + self.assertEqual(repr(objects_only[0]), + '') + self.assertEqual(repr(objects_only[1]), + '') + def test_defer_related_fields(self): self.create_model2abcd()