我们有一个 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 将我创建的两个字段合并为一个字段,例如,通过将其格式化为字符串。这样做的好处是,您可以使用 tuple
构造一个 Counter
以方便查询(使用 values_list()
) .
这个查询肯定会比用 Python 进行计数更有效率。然而,对于可能不那么重要的后台工作。
一个缺点是此代码不可移植;一方面,它不适用于 SQLite,您可能仍在使用它进行测试。在这种情况下,您可能会省去麻烦并立即编写一个原始
查询,这将同样不可移植但更具可读性。
更新
从 1.10 开始,可以使用 expressions 很好地执行此查询, 感谢添加 TruncHour
.以下是解决方案的外观建议:
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 - 有没有办法通过 Django ORM 查询修改日期时间对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38271457/