我有一个像这样的模型:
class Questionnaire(models.Model):
YES_NO_CHOICES = (
(True, 'Yes'),
(False, 'No'),
)
satisfaction = models.BooleanField(choices=YES_NO_CHOICES, default=True)
register = models.DateField(auto_now_add=True)
我需要从这份调查问卷中获得按月分组的回复,并统计"is"和“否”的回复。
例如,我有这样的回复:
{
'2015-11-29': {True: 1, False: 2},
'2015-11-30': {True: 3, False: 1},
'2015-12-01': {True: 5, False: 2},
'2015-12-05': {True: 3, False: 6}
}
我需要一个 Django 查询集来做类似的事情:
{
{'2015-11-01': {True: 4, False: 3},
{'2015-12-01': {True: 8, False: 8}
}
日期并不重要,在模板中我将只使用月份值(01、02、03、...、11、12)。
我正在寻找一种 pythonic 方式来做到这一点,最好是使用 django 中的查询集,而不是字典。
最佳答案
首先,我们需要提取月份和年份值以用于我们的查询。我们通过使用 extra()
来做到这一点。不幸的是,Django 对此没有内置支持。
然后,我们可以使用 values()
按年和月分组。
最后,我们可以使用 annotate()
和条件表达式聚合是/否答案:
from django.db import connections
from django.db.models import Case, IntegerField, Sum, When
conn = connections[Questionnaire.objects.db]
Questionnaire.objects.extra(
select={
'year': conn.ops.date_trunc_sql('year', 'register'),
'month': conn.ops.date_trunc_sql('month', 'register'),
}).values(
'year', 'month'
).annotate(
yes_count=Sum(
Case(When(satisfaction=True, then=1),
output_field=IntegerField()),
),
no_count=Sum(
Case(When(satisfaction=False, then=1),
output_field=IntegerField()),
)
)
您可能还想order_by('year', 'month')
,但这不是代码运行所必需的。
结果将是这样的字典列表:
[{'year': '2015-01-01', 'month': '2015-11-01', 'yes_count': 201, 'no_count': 422},
{'year': '2015-01-01', 'month': '2015-12-01', 'yes_count': 324, 'no_count': 223},
...]
如您所见,year
和month
不是数字,而是字符串。但是,您可以通过拆分轻松提取年份和月份:
year = int(item['year'].split('-')[0])
month = int(item['month'].split('-')[1])
关于python - 计算 Django 中的选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34496728/