如何明确引用字符串值(Python DB API/Psycopg2)
出于某些原因,我想要明确地给一个字符串加上引号(这个字符串会成为构建的SQL查询的一部分),而不是等着cursor.execute
方法在它的第二个参数内容上自动加引号。
我所说的“自动加引号”是指:
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;"
cursor.execute( query, (value,) ) # value will be correctly quoted
我更希望能像这样:
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
READY_TO_USE_QUOTING_FUNCTION(value)
cursor.execute( query ) # value will be correctly quoted, too
在Python的数据库API规范中,是否有这样的低级READY_TO_USE_QUOTING_FUNCTION
?我在PEP 249文档中找不到这样的功能。如果没有,Psycopg2有没有提供这样的函数?如果也没有,Django有没有提供这样的函数?我希望不必自己去写这样的函数...
10 个回答
你应该尽量避免自己去处理引号。正如大家所提到的,这不仅会依赖于具体的数据库,而且引号处理不当是导致SQL注入漏洞的根源。
如果你不想把查询和参数分开传递,那就可以把参数放在一个列表里一起传递:
def make_my_query():
# ...
return sql, (value1, value2)
def do_it():
query = make_my_query()
cursor.execute(*query)
(我可能写错了cursor.execute的语法)这里的重点是,虽然cursor.execute需要多个参数,但这并不意味着你必须把它们一个个单独处理。你可以把它们作为一个列表来处理。
我想你是在找 mogrify 这个函数。
下面是一个例子:
>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"
好吧,我出于好奇去查看了psycopg2的源代码。结果发现我只需要看看示例文件夹就够了 :)
没错,这个内容是针对psycopg2的。基本上,如果你只是想给一个字符串加上引号,你可以这样做:
from psycopg2.extensions import adapt
print adapt("Hello World'; DROP DATABASE World;")
但你可能更想做的是编写并注册你自己的适配器;
在psycopg2的示例文件夹中,你会找到一个文件'myfirstrecipe.py',里面有一个如何以特殊方式转换和加引号的具体类型的例子。
如果你有想要处理的对象,你可以创建一个符合'IPsycopgSQLQuote'协议的适配器(可以查看myfirstrecipe.py示例的文档……其实这是我能找到的唯一相关参考),这个适配器会给你的对象加上引号,然后像这样注册它:
from psycopg2.extensions import register_adapter
register_adapter(mytype, myadapter)
另外,其他的示例也很有趣;特别是'dialtone.py'和'simple.py'。