from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from django.db.models import Sum, Count, Max, When, Case, Value, IntegerField
from django.db.models.functions import TruncDay, TruncMonth, TruncYear
import datetime
from .models import Profile, Team
@login_required
def profile(request):
today = timezone.now()
user_profile = Profile.objects.filter(user=request.user).first()
expenses = user_profile.expense_set.annotate(
field = Case(
When(created__year=today.year, then=1),
When(created__month=today.month, then=2),
When(created__day=today.day, then=3),
default=0,
output_field=IntegerField()
)
)
curent_month_expenses = expenses.filter(created__month=today.month)
expenses_per_day = expenses.annotate(
day=TruncDay('created')).values('day').annotate(
expenses=Count('id'), summary=Sum('amount')
).values('day', 'expenses', 'summary')
expenses_per_month = expenses.annotate(
month=TruncMonth('created')).values('month').annotate(
expenses=Count('id'), summary=Sum('amount')
).values('month', 'expenses', 'summary')
expenses_per_year = expenses.annotate(
year=TruncYear('created')).values('year').annotate(
expenses=Count('id'), summary=Sum('amount')
).values('year', 'expenses', 'summary')
print(expenses_per_year[0])
print(expenses_per_year.first())
context = {
'profile': user_profile,
'curent_month_expenses': curent_month_expenses,
'yearly_expenses': expenses_per_year,
'dayly_expenses': expenses_per_day,
'monthly_expenses': expenses_per_month,
}
return render(request, 'accounts/profile.html', context)
为什么打印语句中的输出不同? 输出:
{'year': datetime.datetime(2020, 1, 1, 0, 0, tzinfo=<UTC>), 'expenses': 6, 'summary': 128400}
{'year': datetime.datetime(2020, 1, 1, 0, 0, tzinfo=<UTC>), 'expenses': 1, 'summary': 1000}
答案 0 :(得分:0)
与普遍的看法相反,qs.first()
不等同于qs[0]
。 qs.first()
将在没有排序的情况下按主键排序,如documentation on .first()
中所述:
返回与查询集匹配的第一个对象;如果存在,则返回
None
没有匹配的对象。如果QuerySet
没有未定义顺序, 然后查询集通过主键自动排序。 如Interaction with default ordering ororder_by()
中所述,这可以影响聚合结果。
如果您通过主键订购,它将因此还原GROUP BY
。您可以自己加入.order_by
来解决此问题:
expenses_per_year = expenses.values(
year=TruncYear('created')
).annotate(
expenses=Count('id'), summary=Sum('amount')
).order_by('year')
您还可以在year=TruncYear('created')
部分中添加.values(..)
,并且无需再次在.values(..)
中包含注释。这使查询更具可读性。