【问题标题】:Django's str(queryset.query) returns invalid SQL if I compare datetimes如果我比较日期时间,Django 的 str(queryset.query) 返回无效 SQL
【发布时间】:2019-12-25 21:11:00
【问题描述】:

我有一个使用 queryset.filter(date__gte=datetime(2011,1,1)) 准备的 Django 查询集

如果我随后调用str(queryset.query),我会在字符串中看到:

... WHERE "App_table"."date" >= 2011-1-1

但是,这是无效的 SQL 代码,就好像我在 Postgresql 中运行它一样,我收到此错误:

... WHERE "App_table"."date" >= 2011-1-1
ERROR:  operator does not exist: date >= integer
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

为什么会发生这种情况?如何让 Django 输出我可以处理的正确 SQL 代码?

【问题讨论】:

    标签: django postgresql django-orm


    【解决方案1】:

    您可以使用query. sql_with_params() 方法。

    print(q.query. sql_with_params())
    

    这将打印查询的参数化版本。

    【讨论】:

    • 这将返回一个元组,其中[0] 是用%s 代替参数的查询,[1] 是参数。如果我这样做queryTuple[0] % queryTuple[1],它会给我与str(q.query) 相同的无效字符串。所以我想我应该使用sql_with_params,在[1] 中手动搜索日期时间并将它们转换为用引号括起来的字符串。 Django 没有办法做到这一点?
    • 这是我评论的可能答案:stackoverflow.com/a/22828674/1307020
    • 是的,关键是现在这是 db 适配器而不是 Django 的责任。
    【解决方案2】:

    添加到 Danel Roseman 的回答中,我如何获得有效的 SQL 语句是使用这个:

    sql, params = unioned_qs.query.sql_with_params()
    
    params_with_quotes = []
    for x in params:
       params_with_quotes.append("'%s'" % x)
    print(sql % tuple(params_with_quotes))
    

    使 Django SQL 查询无效的原因是缺少引号,并且通过将所有值替换为带引号的字符串,SQL 应该是有效的。适用于我的一个边缘案例,但尚未对这一理论进行足够广泛的测试。

    在 Django 3.2 和 Python 3.9 上测试

    【讨论】:

      【解决方案3】:

      如果我的模型字段是models.DateField,这就是我过滤日期的方法:

        queryset.filter(date__gte=datetime.date(2011,1,1))
      

      我猜如果您将字段date 声明为DateTimeField,则比较会起作用。

      【讨论】:

      • 获取str(queryset.query),并将其复制粘贴到您的数据库中。无论该列是否存在,它都不起作用。
      • 在表达式 "WHERE "App_table"."date" >= 2011-1-1" Postgres 将操作数 2011-1-1 插入为 "integer-integer-integer" 在这种情况下评估为整数 2009。因此该语句实际上变成了“日期 >= 整数”,这是一个无效的比较。如果你的表达式是一个日期,你必须告诉 Postgres 这就是你想要的。试试 WHERE "App_table"."date" >= '2011-1-1'::date。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      • 2014-09-11
      • 2016-05-08
      • 1970-01-01
      • 2013-04-09
      相关资源
      最近更新 更多