How to rename fields of an annotated query?

You can change the dictionary key of the annotated value by using keyword arguments:

m = Mainfee.objects.values('collected_by__username').annotate(b=Sum('amount'))

[{'collected_by__username': u'maindesk', 'b': 800}]

There is no quick and easy way to rename a related field, though. You can convert it in Python, but you'll have to ask yourself if that is really necessary:

m = Mainfee.objects.values('collected_by__username').annotate(b=Sum('amount'))
m = [{'a': x['collected_by__username'], 'b': x['b']} for x in m]

Or maybe this is slightly faster:

m = Mainfee.objects.values_list('collected_by__username').annotate(Sum('amount'))
m = [{'a': x[0], 'b': x[1]} for x in m]

Both methods will of course force evaluation of the whole queryset and don't allow further filtering/ordering etc. through the queryset's methods.

Also note that the call to distinct() is redundant when you're using values() or values_list() together with annotate().


You can use an F() expression on collected_by__username:

An F() object represents the value of a model field or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory... F() can be used to create dynamic fields on your models...

If you do this inside an annotate clause, we can 'rename' the field to a. You don't need to use an F() expression when calculating the total. See below:

from django.db.models import F
    
(Mainfee.objects.values('collected_by__username')
    .annotate(a=F('collected_by__username'), b=Sum('amount'))
    .values('a', 'b'))

Making some assumptions about your model, this would produce something like:

<QuerySet [{'a': 'item1', 'b': 1234}, {'a': 'item2', 'b': 4321}]>

Tags:

Django

Orm