You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用psycopg2 sql.SQL对象调用cursor.execute触发TypeError错误

解决Django中使用psycopg2原生更新查询的TypeError问题

问题根源

你遇到的TypeError: "object of type 'Composed' has no len()",本质是Django的代理连接/游标不支持直接传入psycopg2的sql.Composed对象。Django的cursor.execute()期望接收纯字符串SQL和参数元组,而不是psycopg2 sql模块生成的组合对象,直接传入会导致游标尝试将Composed当作字符串处理,触发len()属性缺失的错误。

解决方案

方案1:获取原生psycopg2连接生成完整SQL字符串

Django的connection是代理对象,你可以取出底层的原生psycopg2连接,用它来解析Composed对象为SQL字符串,再传入Django游标执行:

from django.db import connection
from psycopg2 import sql

# 构造安全的更新语句
table = sql.Identifier("your_table")
target_field = sql.Identifier("username")
update_sql = sql.SQL("UPDATE {} SET {} = %s WHERE id = %s").format(table, target_field)

# 获取原生psycopg2连接
raw_connection = connection.connection
# 将Composed对象转为可执行的SQL字符串
sql_string = update_sql.as_string(raw_connection)

# 执行查询
with connection.cursor() as cursor:
    cursor.execute(sql_string, ("new_username", 123))

方案2:使用psycopg2的execute_values批量更新(更高效)

如果是批量更新场景,推荐用psycopg2.extras.execute_values,它能安全处理批量参数,无需手动拼接标识符:

from django.db import connection
from psycopg2.extras import execute_values

# 待更新的数据:(id, new_value)元组列表
update_data = [(1, "alice_updated"), (2, "bob_updated"), (3, "charlie_updated")]
# 基础更新SQL
update_sql = "UPDATE your_table SET username = %s WHERE id = %s"

with connection.cursor() as cursor:
    # 批量执行,page_size控制每次提交的行数
    execute_values(cursor, update_sql, update_data, page_size=1000)

方案3:手动构造安全SQL(适合简单场景)

如果更新逻辑简单,也可以手动用占位符构造SQL,同时用quote_ident方法转义标识符避免SQL注入:

from django.db import connection
from psycopg2.extensions import quote_ident

table_name = "your_table"
field_name = "username"
# 转义表名和字段名,防止SQL注入
safe_table = quote_ident(table_name, connection.connection)
safe_field = quote_ident(field_name, connection.connection)

sql_string = f"UPDATE {safe_table} SET {safe_field} = %s WHERE id = %s"

with connection.cursor() as cursor:
    cursor.execute(sql_string, ("new_name", 456))

关键注意点

  • 不要直接将sql.Identifier、sql.Placeholder或sql.Composed对象传给Django的cursor.execute(),必须先转为字符串。
  • 永远不要手动拼接用户输入的表名、字段名或值,必须用psycopg2的sql模块或quote_ident方法做安全转义,避免SQL注入。

内容的提问来源于stack exchange,提问作者Lax_Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:07:45