首页 > 解决方案 > 在 postgresql 中作为查询执行时,Django ORM 查询失败

问题描述

我有一个像这样的模型

class model(models.Model):
    order_created_time = models.DateTimeField(blank=False, null=False)

我有一个 django 查询,它像这样比较日期时间 -

filters = {'order_created_on__gte':'2018-10-10'}
queryset = model.objects.filter(**filters)
query = str(queryset.query)

它创建一个查询 - 选择 ... where order_created_on >= 2018-10-10 00:00:00

当在 db 上触发时,它会给出错误 - 在“00”或接近“00”时出现语法错误。

如果我通过将日期替换为“2018-10-10”手动在 db 中触发相同的查询,则它可以工作。

现在我实际上尝试了以下方法,但是所有查询在 db 查询中给出相同的文本

filters = {'order_created_on__gte':datetime(2018-10-10)}
filters = {'order_created_on__year__gte':2018, 'order_created_on__month__gte':10, 'order_created_on__day__gte':10}

还尝试将其用作这样的字符串-

filters['order_created_on__gte'] = "'{0}'".format(filters['order_created_on__gte'])

它声明为无效格式,预计 2018-10-10 00:00[:00][TZ]

还使用了范围过滤器,以上所有内容都在最终查询中插入此文本 -

where order_created_on >= 2018-10-10 00:00:00

更新时区也没有任何效果,而不仅仅是从查询中删除 +5:30。

标签: pythondjangopostgresqldjango-rest-framework

解决方案


Django 实际上并不使用str(queryset.query)查询数据库的结果。原因很简单:

数据库采用参数化查询,因此 Django 从不实际将参数放入查询中。它将查询字符串和参数列表分别发送到数据库,数据库确定如何处理它。

print(SomeModel.objects.filter(foo=1).query.sql_with_params())

('SELECT "app_model"."id", "app_model"."some_column", "app_model"."foo" FROM "app_model" WHERE "app_model"."foo" = %s',
 (1,))

然后为简单起见,它所做的只是在您调用__str__()查询时进行纯字符串替换。它在内部不使用它,因此纯粹是为了用户方便。

query, params = SomeModel.objects.filter(foo=1).query.sql_with_params()
print(query % params)

SELECT "app_model"."id", "app_model"."some_column", "app_model"."foo" FROM "app_model" WHERE "app_model"."foo" = 1

自然,当将日期插入到这样的格式字符串中时,它周围没有引号,当您尝试按原样复制粘贴查询并在数据库中使用它时,这会导致错误。他们没有费心实现这一点,因为类型太多而好处太少。

虽然您可以创建自己的函数来自动引用参数,甚至对查询集类进行猴子补丁,以便该__str__()方法返回您需要的内容,但我觉得如果您经常这样做,django-debug-toolbar是要走的路。

django-debug-toolbar 截图


推荐阅读