类型错误:"dict"对象不支持在此查询的第二个实例上引发的索引



所以我正在使用以下代码基于烧瓶中的用户输入构建一个查询:

if empty_indic_form.validate_on_submit():
query='select name, year, value, display_name from literal inner join ent on ent_id=ent.id where display_name in ('
for i in indic_form.indicators.data:
query=query+'''+i+'','
query=query[:-1]+') '
query=query+'and name in ('
for c in order_c:
query=query+c+','
query=query[:-1]+')'
data_return=db.engine.execute(query).fetchall()

我已经确认该查询看起来像它应该的样子,甚至有一个较早的会话,它像我期望的那样返回行代理对象列表。但是现在无论我做什么,我都会收到此错误!

我已经将查询设置为模板中的一个变量,以便我可以将其打印出来,这是我得到的:

select name, year, value, display_name from literal inner join ent on ent_id=ent.id where display_name in ('Energy savings of primary energy (TJ)','Adolescent birth rate (women aged 15-19 years)','Net migration rate','Transmission and distribution losses (%)') and name in ('Burkina Faso', 'Ghana', 'Saudi Arabia', 'Pakistan')

我直接在我的Postgres DB上运行它,结果很棒。

在错误转储中,我注意到data_return=db.engine.execute(query).fetchall()行是使用空字典作为参数构建的,这当然最终会抛出该错误。我可以强迫它不这样做吗?查询对象看起来像上面一样,现在有什么问题?我应该在刷新页面或转到主页时杀死数据库会话吗?

方法中的基本错误是使用字符串连接来构建 SQL 查询。如果indic_form.indicators.dataorder_c是用户提供的数据,例如来自HTTP请求的数据,您可能已经为SQL注入敞开心扉。错误

TypeError: 'dict' object does not support indexing

是这种串联的结果:您的查询字符串包含一个流氓"%",这是 psycopg 占位符语法的一部分 - 通常与 SQLAlchemy 一起使用以与 Postgresql 通信的 DB-API。这正是不应该进行手动连接的原因。正确逃脱可能很困难。

将值列表传递给运算符IN使用 Psycopg2 中的元组适应完成。在 SQLAlchemy 中,您将使用in_列运算符或版本 1.2 中引入的扩展绑定参数。

不幸的是,在您的特定情况下,SQLAlchemy 包装(引擎)有一个问题:由于您的所有参数都是元组,SQLAlchemy 引擎认为您正在尝试将参数元组的迭代对象作为多参数传递给它并自动使用executemany()。您可以使用text()构造来解决此问题,该构造允许将 DB-API 不可知的绑定参数语法和字典作为参数容器:

from sqlalchemy import text
...
if empty_indic_form.validate_on_submit():
# Note that the placeholders shouldn't have enclosing parentheses
query = """SELECT name, year, value, display_name
FROM literal
INNER JOIN ent ON ent_id = ent.id
WHERE display_name IN :display_name
AND name IN :name"""
data_return = db.engine.execute(
text(query), {'display_name': tuple(indic_form.indicators.data),
'name': tuple(order_c)}).fetchall()

回顾一下:切勿使用字符串串联或手动格式构建 SQL 查询。始终使用占位符/绑定参数。

相关内容

最新更新