Skip to main content
 首页 » 编程设计

python之将自定义 SQL 添加到 Django 中的 WHERE 子句中,而不使用 .raw()

2024年11月01日32xing901022

我有一个复杂的 Django ORM 查询,我真的不想将其转换为原始 SQL,因为它是一个非常重要的查询,我想要一致性,我使用了许多 ORM 功能来生成查询,并且它已经过全面测试。

我想在日期时间字段的 WHERE 子句中添加一个过滤器。但是,我只想测试 date 部分,而不是时间。

这是我现有查询的简化版本:

MyTable.objects.filter(date_field__gte=datetime.now().date()) 

但我已将 date_field 转换为 datetime_field,以便在某些情况下更加精确。但是,在这种情况下,我仍然想要进行仅日期比较。像这样的东西:

MyTable.objects.filter(datetime_field__datepartonly__gte=datetime.now().date()) 

在我选择的数据库 postgres 中,这很简单:

SELECT * FROM mytable WHERE DATE(datetime_field) >= ... 

在不将整个查询转换为原始 SQL 的情况下,如何在 Django 中执行此操作?

  • 我试过使用 F(),但您只能指定字段名称,不能指定自定义 SQL。
  • 我尝试使用 Q(),但效果相同。
  • 我尝试了 Django 的 SQL 函数(Sum 等),但只有少数几个,看起来它们专为聚合查询而设计。 我尝试使用别名,但是 you can't use aliases in a WHERE clause, either in Django, or in SQL

我如何在 django 中执行此操作,而不将整个查询转换为原始 SQL?

请您参考如下方法:

datetime 对象的year, month 和day 字段对你可用,但在这里测试后似乎没有允许额外的 __gte 申请到该领域。

这会起作用:

now = datetime.now() 
results = MyTable.objects.filter(datetime_field__year=now.year, datetime_field__month=now.month, datetime_field__day=now.day) 

但是不允许gte。

您始终可以只创建一个从 0:00 开始的日期时间

now = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) 
results = MyTable.objects.filter(datetime_field__gte=now)