【问题标题】:Django query filter, passing a date results in an invalid SQL syntaxDjango查询过滤器,传递日期导致无效的SQL语法
【发布时间】:2011-01-11 14:35:36
【问题描述】:
z = Pokes.objects.filter(
    pokestiming__when_start__lte=datetime.now(), 
    pokestiming__when_end__gte=datetime.now(),
    pokestiming__next_poke__lte=datetime.now(),
    poke_deleted=0,
    poke_operating=1,
)

这是我正在使用的查询。它选择任何 Poke 对象,在日期范围内具有 PokesTiming 对象(外键)。它基本上是一个开始日期和到期日期。

问题是,传递 datetime.now(),尽管它似乎与 django 文档中的语法完全相同,但 SQL 结果是:

SELECT [fieldnames] FROM pokes INNER JOIN pokes_timing ON (pokes.id = pokes_timing.poke_id) WHERE (pokes.poke_deleted = 0 AND @987654 when_start pokes_timing.next_poke pokes_timing.when_end >= 2010-02-01 13:50:48 和 pokes.poke_operating = 1) 限制 21

也就是说,传递的日期只是日期,没有包裹在字符串引号中,这会导致错误并且没有结果。该查询 ^ 由 this method 检索到

我确定我错过了一些愚蠢的东西


楷模:
class Pokes(models.Model):
    poke_title = models.CharField(max_length=135)
    poke_text = models.TextField()
    poke_email = models.CharField(max_length=450)
    poke_email_verified = models.IntegerField(null=True, blank=True)
    poke_key = models.CharField(max_length=30)
    poke_operating = models.IntegerField(default=0)
    poke_deleted = models.IntegerField(default=0)

    class Meta:
        db_table = u'pokes'

    def __unicode__(self):
        return self.poke_title

class PokesTiming(models.Model):
    poke = models.ForeignKey(Pokes)
    interval_min = models.IntegerField(null=True, default=30)
    interval_max = models.IntegerField(null=True, default=120)
    when_start = models.DateTimeField()
    when_end = models.DateTimeField()
    last_run = models.DateTimeField()
    is_single = models.IntegerField(default=0)
    next_poke = models.DateTimeField()

    class Meta:
        db_table = u'pokes_timing'

    def __unicode__(self):
        return self.poke

呸——一定是我。它现在似乎可以通过 Django 工作(我拥有的测试数据一定是错误的 - 它现在返回一个结果)但是原始 SQL 查询不起作用。我猜 Django 在执行之前对它做了什么?无论哪种方式,它似乎都在工作。

【问题讨论】:

  • db.connection.queries 向我展示了同样的事情,但它工作得很好(运行查询确实返回了正确的结果)。您使用的是什么数据库引擎,运行查询时遇到什么错误?
  • 我正在使用 MySQL,它返回以下内容:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '00:00:00 AND pokes_timing ...。如果引用了 datetime 部分,它会起作用,但如果我只是通过 datetime.now(),它不会添加引号。
  • 您能显示PokesTimingPokes 的模型定义吗?
  • 我觉得奇怪的是您调用 datetime.now() 3 次,但得到不同的结果(查看查询 - 其中一个时间是 00:00:00,另外两个不是) .也许您应该将 datetime.now() 的结果分配给某个变量并将其传递给过滤器?
  • 那是我尝试改用 datetime.now().date() 的时候,只是为了看看它是否有效。我还在下面添加了回复。

标签: python django


【解决方案1】:

有一个解决方案(来自https://code.djangoproject.com/ticket/17741):

import datetime
from django.db import connection
from myapp.models import Entry
today_entry_list = Entry.objects.filter(post_date=datetime.date.today())
sql, params = today_entry_list.query.sql_with_params()
cursor = connection.cursor()
cursor.execute('EXPLAIN ' + sql, params)
print(cursor.db.ops.last_executed_query(cursor, sql, params)[8:])

【讨论】:

    【解决方案2】:

    有一个关于这个问题的错误报告已被关闭为无效,因为 Django 没有现有方法可以将实际查询发送到数据库。

    #17612 - SQLite, filter, datefield, datetime no quotes around date in sql query

    您可以看到,此时官方文档中已经提到了这个限制。

    Databases - Parameters not quoted in connection.queries

    【讨论】:

      【解决方案3】:

      Django 将始终将所有字段转换为正确的 SQL 语法,而您手动执行此操作时可能不会这样做。因此你的错误。

      【讨论】:

        猜你喜欢
        • 2021-05-26
        • 2013-08-16
        • 2016-07-10
        • 2020-04-11
        • 2021-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多