I am new to django framework and Python. I have a requirement do aggregation on the fields picked at runtime by the users
class Department(models.Model):
code = models.CharField(max_length=10, primary_key=True)
size = models.IntegerField(blank=True, null=True)
budget = models.IntegerField(blank=True, null=True)
I would like to optionally do the sum of either size,budget or both using **kwarg by doing something like the following
from django.db.models import Avg, Count, Sum
# let Fname has the name of the field to sum on, set by a user input
FName='size'
FList={}
# problem in passing the following
FList['total_size']="Sum(' "+FName+" ')"
data=Department.objects.annotate(**FList)
But I receive the following error
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "c:\python34\lib\site-packages\django\db\models\query.py", line 802, in annotate
is_summary=False)
File "c:\python34\lib\site-packages\django\db\models\sql\query.py", line 1030, in add_aggregate
field_list = aggregate.lookup.split(LOOKUP_SEP)
AttributeError: 'str' object has no attribute 'lookup'
implying from the discussion in the list that Sum is not recognized in the key, value pair
Any help in passing the **kwarg to annotate is appreciated
You're passing the string "Sum(blah)", hence the error.
FList['total_size'] = Sum(FName)
But really there's no reason to use kwargs here at all:
data=Department.objects.annotate(total_size=Sum(FName))
Simplify..
from django.db.models import Avg, Count, Sum
# let Fname has the name of the field to sum on, set by a user input
FName='size'
data=Department.objects.annotate(total_size=Sum(FName))
Since FName
is a string, you don;t need to wrap it with quotes. If you needed tto run a different function, say avg etc...
from django.db.models import Avg, Count, Sum
# let Fname has the name of the field to sum on, set by a user input
FName='size'
function_t = Sum # or Avg, or Count
data=Department.objects.annotate(total_size=function_t(FName))
I hope this helps you get down the path
For those who really wanted to pass a kwarg
to annotate probably 'cause it is defined dinamically you have to do the following:
annotate_filters = {
'sum_foo': Count('foo', distinct=True),
}
if foo:
annotate_filters['sum_foo'] = Count('bar', distinct=True)
Foo.objects.annotate(**annotate_filters)
In this way you can manage different condition and pass them to the annotate function.
Happy coding.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.