A .raw(..) https://docs.djangoproject.com/en/dev/topics/db/sql/#django.db.models.Manager.raw is not它是急切执行的,就像大多数延迟执行的 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")
So the list(..)
强制评估,现在数据库当然会产生错误。然而,即使它是有效的DELETE
查询,它仍然会引发错误,因为这样的查询不会返回任何记录。
为了要做DELETE
调用,Django 手册指定你应该使用游标 [Django-doc] https://docs.djangoproject.com/en/dev/topics/db/sql/#executing-custom-sql-directly:
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
查询,并正确序列化参数。 A.delete()
查询是急切完成的,因此犯上述错误的几率要低得多:如果 ORM 实现正确,那么我们不需要担心这一点。