有没有办法通过Django ORM查询修改日期时间对象?
作者:互联网
我们有一个Django Postgresql数据库,其中包含具有以下内容的对象:
object_date = models.DateTimeField()
作为一个领域.
我们需要每天按小时对对象进行计数,因此我们需要删除一些额外的时间数据,例如:分钟,秒和微秒.
我们可以在python中删除多余的时间数据:
query = MyModel.objects.values('object_date')
data = [tweet['tweet_date'].replace(minute=0, second=0, microsecond=0) for tweet in query
这给我们留下了包含日期和小时的列表.
我的问题:在查询本身中是否有更好,更快,更清洁的方法?
解决方法:
如果只想获取没有时间数据的日期,则可以使用extra来声明计算所得的字段:
query = MyModel.objects
.extra(select={
'object_date_group': 'CAST(object_date AS DATE)',
'object_hour_group': 'EXTRACT(HOUR FROM object_date)'
})
.values('object_date_group', 'object_hour_group')
但是,您不能从中获得太多收益;数据库现在向您发送更多数据.
但是,通过这些附加字段,您可以使用聚合通过添加以下一行来立即获取所需的计数:
query = MyModel.objects
.extra(select={
'object_date_group': 'CAST(object_date AS DATE)',
'object_hour_group': 'EXTRACT(HOUR FROM object_date)'
})
.values('object_date_group', 'object_hour_group')
.annotate(count=Count('*'))
或者,您可以使用任何有效的SQL,例如,通过将我将两个字段格式化为字符串来将我创建的两个字段组合为一个字段.这样做的好处是,您可以使用元组构造一个Counter以便于查询(使用values_list()).
这个查询肯定比在Python中进行计数更有效.但是,对于后台工作而言,可能并不那么重要.
缺点是此代码不可移植.一方面,它不适用于您仍然用于测试目的的SQLite.在这种情况下,您可能会省去麻烦,并立即编写原始查询,这将像不可移植但更易读.
更新资料
由于添加了TruncHour
,从1.10版本开始,可以使用expressions很好地执行此查询.以下是有关解决方案外观的建议:
from collections import Counter
from django.db.models import Count
from django.db.models.functions import TruncHour
counts_by_group = Counter(dict(
MyModel.objects
.annotate(object_group=TruncHour('object_date'))
.values_list('object_group')
.annotate(count=Count('object_group'))
)) # query with counts_by_group[datetime.datetime(year, month, day, hour)]
它优雅,高效且便携.
标签:python-3-x,django-queryset,python,django,django-models 来源: https://codeday.me/bug/20191118/2028147.html