#12608 closed (fixed)
Inconsistent results from values and values_list when using annotate
| Reported by: | Matt McClanahan | Owned by: | coleifer |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Keywords: | values_list annotate | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
To group users by email and get a count, one might do:
>>> User.objects.values('email').annotate(Count('email'))
[{'email__count': 2, 'email': u'user@example.com'}]
However, values_list discards the annotated value:
>>> User.objects.values_list('email').annotate(Count('email'))
[(u'user@example.com',)]
Attachments (2)
Change History (11)
comment:1 by , 16 years ago
| Component: | Uncategorized → Database layer (models, ORM) |
|---|---|
| Keywords: | values_list annotate added |
comment:2 by , 16 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:3 by , 16 years ago
| Has patch: | set |
|---|
by , 16 years ago
| Attachment: | 12608.patch added |
|---|
comment:4 by , 16 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:5 by , 16 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
comment:6 by , 16 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
by , 16 years ago
| Attachment: | 12608_fix.diff added |
|---|
comment:8 by , 16 years ago
Note:
See TracTickets
for help on using tickets.
I patched the ValuesList iterator to include aggregates in the fields if specified:
diff --git a/django/db/models/query.py b/django/db/models/query.py index 8cb3dbe..31b3333 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -954,7 +954,8 @@ class ValuesListQuerySet(ValuesQuerySet): # If a field list has been specified, use it. Otherwise, use the # full list of fields, including extras and aggregates. if self._fields: - fields = self._fields + fields = list(self._fields) + filter(lambda f: f not in self._fields, + aggregate_names) else: fields = names diff --git a/tests/modeltests/aggregation/models.py b/tests/modeltests/aggregation/models.py index 9ed638e..0e8d881 100644 --- a/tests/modeltests/aggregation/models.py +++ b/tests/modeltests/aggregation/models.py @@ -362,4 +362,7 @@ True >>> Book.objects.filter(pk=1).annotate(mean_age=Avg('authors__age')).values_list('mean_age', flat=True) [34.5] +>>> Book.objects.values_list('price').annotate(count=Count('price')).order_by('-count', 'price') +[(Decimal('29.69'), 2), (Decimal('23.09'), 1), (Decimal('30'), 1), (Decimal('75'), 1), (Decimal('82.8'), 1)] + """}In [1]: from django.contrib.auth.models import User In [2]: from django.db.models import Count In [3]: User.objects.values_list('email').annotate(Count('email')) Out[3]: [(u'user@example.com', 2)] In [4]: User.objects.values('email').annotate(Count('email')) Out[4]: [{'email__count': 2, 'email': u'user@example.com'}] In [5]: User.objects.values_list('email') Out[5]: [(u'user@example.com',), (u'user@example.com',)]