Django从日期时间开始计算日期

时间:2017-04-04 22:48:39

标签: django date datetime django-models django-queryset

我正在尝试计算用户从DateTime字段注册的日期。在数据库中,这被存储为'2016-10-31 20:49:38',但我只对'2016-10-31'的日期感兴趣。

原始SQL查询是:

select DATE(registered_at) registered_date,count(registered_at) from User 
where course='Course 1' group by registered_date;

可以使用'extra',但我读过这个已被弃用,不应该这样做。它的工作原理如下:

User.objects.all()
    .filter(course='Course 1')
    .extra(select={'registered_date': "DATE(registered_at)"})
    .values('registered_date')
    .annotate(**{'total': Count('registered_at')})

是否可以不使用额外的?

我读到可以使用TruncDate,我认为这是正确的查询集但是它不起作用:

User.objects.all()
    .filter(course='Course 1')
    .annotate(registered_date=TruncDate('registered_at'))
    .values('registered_date')
    .annotate(**{'total': Count('registered_at')})

我得到<QuerySet [{'total': 508346, 'registered_date': None}]>因此TruncDate出现了问题。

如果有人比我更了解这一点,并且可以指出我正确的方向,我会非常感激。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

我试图做一些非常相似的事情并且遇到与你一样的问题。我设法通过在应用if (i < WIDTH - 1) { if (map[i + 1][j] == 1) { ... } if (map[i + 1][j] == 0) { ... } } 注释后添加order_by子句来解决我的问题。所以我想这也适合你:

TruncDate

希望这有帮助吗?!

答案 1 :(得分:0)

这是通过使用`registered_at__date'来使用TruncDate的替代方法,而Django会为您进行截断。

from django.db.models import Count
from django.contrib.auth import get_user_model

metrics = {
    'total': Count('registered_at__date')
}
get_user_model().objects.all()
    .filter(course='Course 1')
    .values('registered_at__date')
    .annotate(**metrics)
    .order_by('registered_at__date')

对于Postgresql,这将转换为数据库查询:

SELECT
    ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date,
    COUNT("auth_user"."registered_at") AS "total"
FROM
    "auth_user"
GROUP BY
    ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date
ORDER BY
    ("auth_user"."registered_at" AT TIME ZONE 'Asia/Kolkata')::date ASC;

从以上示例中,您可以看到Django ORM颠倒了SELECTGROUP_BY参数。在Django ORM中,.values()大致控制GROUP_BY参数,而.annotate()控制SELECT列以及需要完成的聚合。感觉有些奇怪,但是当您掌握它时很简单。