如何使用 django ORM 在 postgres 中仅选择日期部分
Posted
技术标签:
【中文标题】如何使用 django ORM 在 postgres 中仅选择日期部分【英文标题】:How to select only date part in postgres by using django ORM 【发布时间】:2017-05-10 14:20:08 【问题描述】:我的后端设置如下
Postgres 9.5 Python 2.7 Django 1.9我有一个日期时间类型的表,名为createdAt
。我想使用 Django ORM 选择只有日期部分的字段,并按createdAt
分组。
例如,这个createdAt
字段可能存储2016-12-10 00:00:00+0
、2016-12-11 10:10:05+0
、2016-12-11 17:10:05+0
...等。
使用Djanggo ORM,输出应该是2016-12-10
、2016-12-11
。对应的sql应该类似于:SELECT date(createdAt) FROM TABLE GROUP BY createdAt
。
谢谢。
【问题讨论】:
您是在尝试按日期使用分组函数(例如 count(*))还是仅以此为例?如果您只需要显示模板过滤器,或者如果经常使用它,则可以使用模板过滤器,也许可以创建一个模型属性。 【参考方案1】:你可以试试:
-
使用
__date
运算符按DateTimeField
过滤,日期部分为:createAt__date
,这类似于__lt
或__gt
。
使用annotate/Func/F 创建一个基于createAt
的额外字段,仅显示日期部分。
使用values
和annotate
、Count
/Sum
创建group by
查询。
示例代码
from django.db import models
from django.db.models import Func, F, Count
class Post(models.Model):
name = models.CharField('name', max_length=255)
createAt = models.DateTimeField('create at', auto_now=True)
Post.objects.filter(createAt__date='2016-12-26') # filter the date time field for specify date part
.annotate(createAtDate=Func(F('createAt'), function='date')) # create an extra field, named createAtDate to hold the date part of the createAt field, this is similar to sql statement: date(createAt)
.values('createAtDate') # group by createAtDate
.annotate(count=Count('id')) # aggregate function, like count(id) in sql statement
输出
['count': 2, 'createAtDate': datetime.date(2016, 12, 26)]
注意:
-
为了指定每个方法的功能,我将长语句分成多个片段,因此在将回车粘贴到代码时需要删除它。
当您在应用程序中打开时区时,例如
USE_TZ = True
,在 django 中比较两个日期时需要更加小心。当您进行上述查询时,时区很重要。
希望它会有所帮助。 :)
【讨论】:
【参考方案2】:Django 提供Manager.raw()
来对模型执行原始查询,但原始查询必须包含在您的情况下无用的主键。如果Manager.raw()
不够,您可能需要执行未完全映射到模型的查询,您始终可以直接访问数据库,使用connection
完全围绕模型层进行路由。 connection
对象代表默认的数据库连接。所以你可以像这样执行查询。
from django.db import connection
#acquire cursor object by calling connection.cursor()
cursor = connection.cursor()
cursor.execute('SELECT created_at from TABLE_NAME GROUP BY created_at')
执行查询后,您可以遍历游标对象以获取查询结果。
【讨论】:
以上是关于如何使用 django ORM 在 postgres 中仅选择日期部分的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 django 1.7.3/postgres 迁移在数据库中设置默认列值?
如何在不使用字段名的情况下运行 django orm 查询?
惯用/快速 Django ORM 检查 mysql/postgres 上是不是存在
postgres 上的 Django unique_together:由 ORM 或 DB 强制执行?