如何使用 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+02016-12-11 10:10:05+02016-12-11 17:10:05+0 ...等。

使用Djanggo ORM,输出应该是2016-12-102016-12-11。对应的sql应该类似于:SELECT date(createdAt) FROM TABLE GROUP BY createdAt

谢谢。

【问题讨论】:

您是在尝试按日期使用分组函数(例如 count(*))还是仅以此为例?如果您只需要显示模板过滤器,或者如果经常使用它,则可以使用模板过滤器,也许可以创建一个模型属性。 【参考方案1】:

你可以试试:

    使用__date 运算符按DateTimeField 过滤,日期部分为:createAt__date,这类似于__lt__gt。 使用annotate/Func/F 创建一个基于createAt 的额外字段,仅显示日期部分。 使用valuesannotateCount/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 强制执行?

Django - Django ORM 如何管理用户在数据库中上传的表

带有 Postgres 的 ASP.NET MVC; ORM 推荐?