#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 [email protected].
To post to this group, send email to [email protected].
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