查询集.query中的潜在Django bug?

7 投票
1 回答
2062 浏览
提问于 2025-04-15 23:16

声明:我还在学习Django,所以可能有些地方理解得不太对,但我看不出有什么问题...

我正在使用Python 2.6.1和Django 1.2.1。

(InteractiveConsole)
>>> from myproject.myapp.models import *
>>> qs = Identifier.objects.filter(Q(key="a") | Q(key="b"))
>>> print qs.query
SELECT `app_identifier`.`id`, `app_identifier`.`user_id`, 
`app_identifier`.`key`, `app_identifier`.`value` FROM
`app_identifier` WHERE (`app_identifier`.`key` = a  OR
`app_identifier`.`key` = b )
>>>

注意到它没有给“a”或“b”加上引号吗!现在,我已经确认这个查询是可以正常执行的。所以,实际上,它确实是可以工作的。但是,打印出来的查询结果却是错的,这真的让人很烦。特别是如果我做了这样的事情...

>>> qs = Identifier.objects.filter(Q(key=") AND") | Q(key="\"x\"); DROP TABLE      
                `app_identifier`"))
>>> print qs.query
SELECT `app_identifier`.`id`, `app_identifier`.`user_id`,
`app_identifier`.`key`, `app_identifier`.`value` FROM
`app_identifier` WHERE (`app_identifier`.`key` = ) AND  OR
`app_identifier`.`key` = "x"); DROP TABLE `app_identifier` )
>>> 

如你所见,这不仅生成了完全错误的SQL代码,还可能导致SQL注入攻击的风险。显然,这种情况实际上是不会发生的,原因有很多(1. 语法完全错误,这是故意的,目的是为了展示Django行为的奇怪之处。2. Django不会像这样执行查询,它会像应有的那样加上引号和斜杠等)。

但是,这真的让调试变得很困惑,也让我怀疑我的Django安装是否出了问题。

你们遇到过这种情况吗?如果有/没有,你们使用的Python和Django版本是什么?

有什么想法吗?

1 个回答

11

好的,我刚刚搞明白了。这不是一个错误。查看一下django/db/models/sql/query.py的源代码:

160     def __str__(self):
161         """
162         Returns the query as a string of SQL with the parameter values
163         substituted in.
164 
165         Parameter values won't necessarily be quoted correctly, since that is
166         done by the database interface at execution time.
167         """
168         sql, params = self.get_compiler(DEFAULT_DB_ALIAS).as_sql()
169         return sql % params

(http://code.djangoproject.com/browser/django/trunk/django/db/models/sql/query.py)

一切都正常运作。:)

撰写回答