django models.py
class mymodel(models.Model):
date_check = models.DateField()
item_1 = models.NullBooleanField()
item_2 = mod`enter code here`els.NullBooleanField()
item_3 = models.NullBooleanField()
item_4 = models.NullBooleanField()
item_5 = models.NullBooleanField()
Task:
>>> from .models import mymodel
>>>
>>> a_list = ['item_1', 'item_2', 'item_3', 'item_4', 'item_5', 'item_5', ]
>>> a_year = 2018
>>> param1 = {}
>>> param2 = {}
>>> param3 = {}
>>> for item in a_list :
>>> param1[item] = mymodel.objects.filter(date_check__year = a_year, item=True).count()
>>> param2[item] = mymodel.objects.filter(date_check__year = a_year, item=False).count()
>>> param3[item] = mymodel.objects.filter(date_check__year = a_year, item=None).count()
.....error here
how do we call field name from list?
Here item
is interpreted as an identifier, so the name of the parameter is item
. The fact that there is a variable with the same name and a certain value, is not relevant.
We can however fix this by constructing a dictionary that maps item
(so here it will be replaced with the corresponding value) to True
, False
, and None
. We the can use this dictionary as the named parameters dictionary* by using two consecutive asterisks as prefix:
for item in a_list :
param1[item] = mymodel.objects.filter(date_check__year=a_year, **{item: True}).count()
param2[item] = mymodel.objects.filter(date_check__year=a_year, **{item: False}).count()
param3[item] = mymodel.objects.filter(date_check__year=a_year, **{item: None}).count()
Note that this will hoever result in multiple queries. We can reduce the amount of querying by for example aggregating over a selection, like:
qs = mymodel.objects.filter(date_check__year=a_year)
for item in a_list :
data = qs.aggregate(
p1=Count('pk', filter=Q(**{item: True}))
p2=Count('pk', filter=Q(**{item: False}))
p3=Count('pk', filter=Q(**{item: None}))
)
param1[item] = data['p1'] or 0
param2[item] = data['p2'] or 0
param3[item] = data['p3'] or 0
Here we thus count three things per query: the number of True
s, False
s and None
s. We can actually extend this logic, and even count everything in a single query, which is typically more efficient (this is not per se true, but making a query typically results in some overhead to construct a query, interpret the query at the database side, serializing results, etc.).