#26565: Allow Prefetch query to returns aggregations
----------------------------------------------+----------------------------
     Reporter:  mlorant                       |      Owner:  nobody
         Type:  Bug                           |     Status:  new
    Component:  Database layer (models, ORM)  |    Version:  1.9
     Severity:  Normal                        |   Keywords:  prefetch,
                                              |  values
 Triage Stage:  Unreviewed                    |  Has patch:  0
Easy pickings:  0                             |      UI/UX:  0
----------------------------------------------+----------------------------
 I came across a use case that does not seems to be possible using the
 Django ORM on Django 1.9.

 Let's says I want to get all objects from a `Order` model and prefetch for
 each order all pay lines, grouped per code, to get a list similar to:
 `[{'code': 'A', 'number': 3, 'amount': 1000}, {'code': 'B', 'number': 1,
 'amount': 5000}]` if the order has four PayRollLine associated, with 3
 where code=A and 1 where code=B.

 {{{
 # Query that will be used inside the `Prefetch` object later
 # Let's assume quantity and unit_amount can't be null in the query
 # to avoid extra Coalesce...
 prefetch_qs = (
     PayrollLine.objects.values('code').annotate(
         number=ExpressionWrapper(
             Sum(F('quantity')), output_field=DecimalField()
         ),
         amount=ExpressionWrapper(
             Sum(F('unit_amount') * F('quantity')),
 output_field=DecimalField()
         ),
     )
 )
 print(
     Order.objects.all()
     .prefetch_related(
         Prefetch('pay_lines', queryset=prefetch_qs,
 to_attr='pay_lines_grouped')
     )
 )
 }}}

 The first query works fine alone, outside the prefetch object. But, when
 executing the second query, Django raises an exception:

 {{{
     Traceback (most recent call last):
       [...]
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/query.py", line 234, in __repr__
         data = list(self[:REPR_OUTPUT_SIZE + 1])
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/query.py", line 258, in __iter__
         self._fetch_all()
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/query.py", line 1076, in _fetch_all
         self._prefetch_related_objects()
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/query.py", line 656, in
 _prefetch_related_objects
         prefetch_related_objects(self._result_cache,
 self._prefetch_related_lookups)
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/query.py", line 1457, in
 prefetch_related_objects
         obj_list, additional_lookups = prefetch_one_level(obj_list,
 prefetcher, lookup, level)
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/query.py", line 1556, in prefetch_one_level
         prefetcher.get_prefetch_queryset(instances,
 lookup.get_current_queryset(level)))
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/fields/related_descriptors.py", line 544, in
 get_prefetch_queryset
         instance = instances_dict[rel_obj_attr(rel_obj)]
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/fields/related.py", line 597, in
 get_local_related_value
         return self.get_instance_value_for_fields(instance,
 self.local_related_fields)
       File "/data/.virtualenvs/ORFEO/local/lib/python2.7/site-
 packages/django/db/models/fields/related.py", line 605, in
 get_instance_value_for_fields
         opts = instance._meta
     AttributeError: 'dict' object has no attribute '_meta'
 }}}

 Looks like Django can't work with dict in prefetch_related... On IRC,
 someone point me to [this PR](https://github.com/django/django/pull/6478)
 that could resolve my problem but I think it should be verified with unit
 tests.

--
Ticket URL: <https://code.djangoproject.com/ticket/26565>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/050.275dd503dcd42166eb62ebea25af54a9%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to