ald*_*ido 15 python django postgresql
如何在不使用额外的情况下按月计算总数?
我目前正在使用:
例.
到目前为止我尝试过的.
#Doesn't work for me but I don't mind because I don't want to use extra
truncate_month = connection.ops.date_trunc_sql('month','day')
invoices = Invoice.objects.filter(is_deleted = False,company = company).extra({'month': truncate_month}).values('month').annotate(Sum('total'))
----
#It works but I think that it's too slow if I query a big set of data
for current_month in range(1,13):
Invoice.objects.filter(date__month = current__month).annotate(total = Sum("total"))
Run Code Online (Sandbox Code Playgroud)
而这一个,答案似乎很好,但我无法导入TruncMonth模块.
PS我知道这个问题已被多次询问,但我没有看到任何答案.
谢谢!
解决方案:
感谢@ Vin-G的回答.
Vin*_*n-G 24
首先,你必须创建一个可以为你提取月份的函数:
from django.db import models
from django.db.models import Func
class Month(Func):
function = 'EXTRACT'
template = '%(function)s(MONTH from %(expressions)s)'
output_field = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)
之后你需要做的就是
values()
Sum()
重要提示:如果模型类具有元选项中指定的默认顺序,则必须添加空order_by()
子句.这是因为https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#interaction-with-default-ordering-or-order-by
order_by()
在选择输出数据时,将使用在查询集的一部分中提到的字段(或在模型的默认排序中使用的字段),即使它们未在values()
调用中另外指定.这些额外字段用于将"喜欢"结果组合在一起,并且它们可以使其他相同的结果行看起来是分开的.
如果您不确定,您可以添加空order_by()
子句,无任何不利影响.
即
from django.db.models import Sum
summary = (Invoice.objects
.annotate(m=Month('date'))
.values('m')
.annotate(total=Sum('total'))
.order_by())
Run Code Online (Sandbox Code Playgroud)
请参阅此处的完整要点:https://gist.github.com/alvingonzales/ff9333e39d221981e5fc4cd6cdafdd17
如果您需要更多信息:
有关创建自己的Func类的详细信息:https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions
有关values()子句的详细信息,(注意它与子句顺序的annotate()交互方式):https: //docs.djangoproject.com/en/1.9/topics/db/aggregation/#values
annotate()和values()子句应用于查询的顺序非常重要.如果values()子句在annotate()之前,则将使用values()子句描述的分组计算注释.
小智 9
result = (
invoices.objects
.all()
.values_list('created_at__year', 'created_at__month')
.annotate(Sum('total'))
.order_by('created_at__year', 'created_at__month')
)
Run Code Online (Sandbox Code Playgroud)
itertools.groupby
是 Python 中的高性能选项,可以与单个 db 查询一起使用:
from itertools import groupby
invoices = Invoice.objects.only('date', 'total').order_by('date')
month_totals = {
k: sum(x.total for x in g)
for k, g in groupby(invoices, key=lambda i: i.date.month)
}
month_totals
# {1: 100, 3: 100, 4: 500, 7: 500}
Run Code Online (Sandbox Code Playgroud)
我不知道纯 django ORM 解决方案。该date__month
过滤器是非常有限的,并且不能被使用在values
,order_by
等
归档时间: |
|
查看次数: |
8871 次 |
最近记录: |