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

Django中传递kwargs参数到原生PostgreSQL SQL的正确方法

问题解决:Django原生SQL动态传递标识符与参数的正确方式

错误原因

你遇到的问题本质是:cursor.execute的参数化机制是为SQL值设计的,不是为标识符(列名、JSON键名这类)设计的。当你把列名cart用参数%(field)s传递时,它会被自动加上单引号,变成字符串'cart',导致SQL语法错误——因为->>操作符需要左边是JSON类型的列,而不是字符串。

正确实现方式

区分标识符和值,分开处理

  • 标识符(列名、表名等):需要用Django提供的转义方法处理后拼接进SQL,不能用参数化
  • 值(JSON键、查询条件值等):可以安全地用cursor.execute的参数化传递

代码示例

from django.db import connection

with connection.cursor() as cursor:
    # 转义列名(标识符),自动适配数据库的引号规则(PostgreSQL用双引号)
    escaped_field = connection.ops.quote_name('cart')
    # SQL中,标识符用转义后的结果,JSON键用参数化传递
    query = f"SELECT sum(({escaped_field}->> %(key)s)::int) as total_price FROM core_foo;"
    params = {
        'key': 'total_price',
    }
    cursor.execute(query, params)
    row = cursor.fetchone()
    print(row)

如果你的列名也是动态生成的(比如从变量获取),同样先转义再拼接:

dynamic_field = 'cart'  # 可以是动态变量
escaped_field = connection.ops.quote_name(dynamic_field)
query = f"SELECT sum(({escaped_field}->> %(key)s)::int) as total_price FROM core_foo;"

针对你的问题解答

  1. 是否需要带单/双引号?

    • 对于标识符(列名、表名):不需要自己加,用connection.ops.quote_name()会自动添加符合数据库规范的引号(比如PostgreSQL加双引号,MySQL加反引号),同时处理特殊字符转义
    • 对于值(JSON键、条件值):不需要自己加,cursor.execute的参数化会自动添加引号并转义特殊字符,避免SQL注入
  2. 还是不需要带单/双引号?
    总结:标识符靠转义方法自动加规范引号,值靠参数化自动处理,都不需要你手动加引号。

关键提醒

永远不要直接拼接未转义的用户输入作为标识符(比如列名、表名),必须用quote_name转义,否则会存在SQL注入风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 07:44:53