【问题标题】:Django ORM raw delete query not deleting recordsDjango ORM原始删除查询不删除记录
【发布时间】:2019-07-24 07:54:29
【问题描述】:

我使用 raw_sql 查询是为了方便我的数据库最小化我正在删除额外的记录。通过这个查询

#d is from a loop and has values
res=MyModel.objects.raw("DELETE FROM mydb_mymodel WHERE mydb_mymodel.s_type = '%s' and mydb_mymodel.barcode = '%s' and mydb_mymodel.shopcode = '%s' and mydb_mymodel.date = '%s'" ,[d.s_type,d.barcode,d.shopcode,d.date])

不是删除数据库中的记录而是删除记录

当我执行res.query 并从postgres 控制台运行它时,它可以工作!

是的,我可以使用

MyModel.objects.filter(s_type=d.s_type,barcode=d.barcode,
shopcode=d.shopcode,date=d.date).delete()

但是我在 raw_sql 中缺少什么?

【问题讨论】:

  • 如果你去掉这里的引号,所以%s而不是'%s'?话虽如此,Django 的真正优势之一是内置的 ORM,它可以抽象出您的数据库,并进行更易读的查询(并自行完成所有映射、序列化等)。
  • 我尝试使用引号进行查询,否则我会出错!所以引号在这里很好,因为它们是 postgres 查询语法的一部分,并且是字符串类型,我比较像 mydb_mymodel.s_type = 'sale' 而不是 mydb_mymodel.s_type = sale

标签: django postgresql django-models django-orm


【解决方案1】:

.raw(..)不是急切地执行,它是,就像大多数 Django ORM 查询延迟执行一样。因此,它返回一个RawQuerySet 对象,其中包含对象中的查询。例如:

>>> User.objects.raw('BLA BLA BLA', [])
<RawQuerySet: BLA BLA BLA>

BLA BLA BLA 这样的查询没有任何意义:数据库会出错,但我们仍然会检索到RawQuerySet

您可以通过例如迭代它来强制评估,然后我们得到:

>>> list(User.objects.raw('BLA BLA BLA', []))
Traceback (most recent call last):
  File "/djangotest/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/djangotest/env/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 71, in execute
    return self.cursor.execute(query, args)
  File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 250, in execute
    self.errorhandler(self, exc, value)
  File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
    raise errorvalue
  File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 247, in execute
    res = self._query(query)
  File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 412, in _query
    rowcount = self._do_query(q)
  File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/cursors.py", line 375, in _do_query
    db.query(q)
  File "/djangotest/env/lib/python3.6/site-packages/MySQLdb/connections.py", line 276, in query
    _mysql.connection.query(self, query)
_mysql_exceptions.ProgrammingError: (1064, "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 'BLA BLA BLA' at line 1")

所以list(..) 强制评估,现在数据库当然会产生错误。然而,即使它是一个有效的 DELETE 查询,它仍然会引发错误,因为这样的查询不会返回任何记录。

为了进行DELETE 调用,Django 手册指定您应该use a cursor [Django-doc]

from django.db import connection

with connection.cursor() as cursor:
    cursor.execute(
        "DELETE FROM mydb_mymodel WHERE s_type = '%s' AND barcode = '%s' AND shopcode = '%s' AND date = '%s'" ,
        [d.s_type,d.barcode,d.shopcode,d.date]
    )

但我认为指定它可能要简单得多:

MyModel.objects.filter(
    s_type=d.s_type,
    barcode=d.barcode,
    shopcode=d.shopcode,
    date=d.date
).delete()

这将构造一个DELETE 查询,并正确序列化参数。 .delete() 查询是急切完成的,因此犯上述错误的几率要低得多:如果 ORM 实现正确,那么我们无需担心。

【讨论】:

  • 是的!你是对的,查询集是 lazy 并且你对 quotes 也是正确的,因为它被格式化为''sale'',在运行时会抛出错误。我检查了一下,它可以工作,谢谢你这么多:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-04
  • 2019-01-04
  • 2014-10-28
  • 2021-03-22
  • 2011-07-09
  • 1970-01-01
相关资源
最近更新 更多