Skip to content

AttributeError Using .alias() On Polymorphic Querysets #658

@trumpet2012

Description

@trumpet2012

Using .alias() on a polymorphic queryset, causes an AttributeError to be thrown.

The workaround is to use annotate instead of alias.

Minimal reproduction using the example project from the repo:

from pexp.models import TestModelA, TestModelB
from django.db import models
from django.db.models import functions

TestModelB.objects.create(field1="field1", field2="field2")

# Evaluating this queryset throws the AttributeError
list(TestModelA.objects.alias(lower_field1=functions.Lower(models.F("field1"))))

The full traceback for the error:

AttributeError                            Traceback (most recent call last)
File ~/code/django-polymorphic/.venv/lib/python3.10/site-packages/IPython/core/formatters.py:770, in PlainTextFormatter.__call__(self, obj)
    763 stream = StringIO()
    764 printer = pretty.RepresentationPrinter(stream, self.verbose,
    765     self.max_width, self.newline,
    766     max_seq_length=self.max_seq_length,
    767     singleton_pprinters=self.singleton_printers,
    768     type_pprinters=self.type_printers,
    769     deferred_pprinters=self.deferred_printers)
--> 770 printer.pretty(obj)
    771 printer.flush()
    772 return stream.getvalue()

File ~/code/django-polymorphic/.venv/lib/python3.10/site-packages/IPython/lib/pretty.py:419, in RepresentationPrinter.pretty(self, obj)
    408                         return meth(obj, self, cycle)
    409                 if (
    410                     cls is not object
    411                     # check if cls defines __repr__
   (...)
    417                     and callable(_safe_getattr(cls, "__repr__", None))
    418                 ):
--> 419                     return _repr_pprint(obj, self, cycle)
    421     return _default_pprint(obj, self, cycle)
    422 finally:

File ~/code/django-polymorphic/.venv/lib/python3.10/site-packages/IPython/lib/pretty.py:794, in _repr_pprint(obj, p, cycle)
    792 """A pprint that just redirects to the normal repr function."""
    793 # Find newlines and replace them with p.break_()
--> 794 output = repr(obj)
    795 lines = output.splitlines()
    796 with p.group():

File ~/code/django-polymorphic/src/polymorphic/query.py:490, in PolymorphicQuerySet.__repr__(self, *args, **kwargs)
    488 def __repr__(self, *args, **kwargs):
    489     if self.model.polymorphic_query_multiline_output:
--> 490         result = ",\n  ".join(repr(o) for o in self.all())
    491         return f"[ {result} ]"
    492     else:

File ~/code/django-polymorphic/.venv/lib/python3.10/site-packages/django/db/models/query.py:384, in QuerySet.__iter__(self)
    369 def __iter__(self):
    370     """
    371     The queryset iterator protocol uses three nested iterators in the
    372     default case:
   (...)
    382            - Responsible for turning the rows into model objects.
    383     """
--> 384     self._fetch_all()
    385     return iter(self._result_cache)

File ~/code/django-polymorphic/.venv/lib/python3.10/site-packages/django/db/models/query.py:1949, in QuerySet._fetch_all(self)
   1947 def _fetch_all(self):
   1948     if self._result_cache is None:
-> 1949         self._result_cache = list(self._iterable_class(self))
   1950     if self._prefetch_related_lookups and not self._prefetch_done:
   1951         self._prefetch_related_objects()

File ~/code/django-polymorphic/src/polymorphic/query.py:63, in PolymorphicModelIterable._polymorphic_iterator(self, base_iter)
     60         reached_end = True
     61         break
---> 63 real_results = self.queryset._get_real_instances(base_result_objects)
     65 for o in real_results:
     66     yield o

File ~/code/django-polymorphic/src/polymorphic/query.py:460, in PolymorphicQuerySet._get_real_instances(self, base_result_objects)
    458 if self.query.annotations:
    459     for anno_field_name in self.query.annotations.keys():
--> 460         attr = getattr(base_object, anno_field_name)
    461         setattr(real_object, anno_field_name, attr)
    463 if self.query.extra_select:

AttributeError: 'TestModelA' object has no attribute 'lower_field1'

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions