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

如何在Django原生SQL的WHERE IN语句中传入列表参数?

Django原生SQL中UUID列表注入WHERE IN的正确姿势

问题背景

需要在Django原生SQL的WHERE ... IN (...)语句中注入UUID列表,示例UUID列表:

list_of_uuids = [
  "<UUID_1>",
  "<UUID_2>"
]

期望生成的目标SQL:

SELECT * 
FROM some_model_table 
WHERE some_model_table.uuid IN ( "<UUID_1>", "<UUID_2>" )

直接使用raw()传递列表时,参数会被解析为SQL数组,触发语法错误:

django.db.utils.ProgrammingError: syntax error at or near "ARRAY":

LINE X: WHERE uuid IN ARRAY['00123...

将数组包裹为(ARRAY[...])会因类型不匹配报错,且不能使用.format()拼接(存在SQL注入风险),同时实际查询逻辑复杂,无法通过ORM的filter(uuid__in=...)实现。

可行解决方案

方法1:手动构造参数占位符(通用所有数据库)

根据UUID列表的长度,生成对应数量的%s占位符,再将列表拆分为参数传递,全程保持参数化,无注入风险:

# 根据UUID数量生成占位符,比如2个UUID生成 "%s, %s"
placeholders = ", ".join(["%s"] * len(list_of_uuids))
# 构造带占位符的SQL语句
sql = f"SELECT * FROM some_model_table WHERE some_model_table.uuid IN ({placeholders})"
# 执行原生查询,直接传递UUID列表作为参数
query_set = SomeModel.objects.raw(sql, list_of_uuids)

方法2:PostgreSQL专属数组运算符

如果使用PostgreSQL数据库,可以用= ANY()替代IN,直接传递列表参数即可,数据库会自动解析数组:

sql = "SELECT * FROM some_model_table WHERE some_model_table.uuid = ANY(%s)"
query_set = SomeModel.objects.raw(sql, [list_of_uuids])

最终生成的SQL为WHERE uuid = ANY(ARRAY['uuid1', 'uuid2']),PostgreSQL可直接识别,且保持参数化安全。

方法3:借助游标生成适配SQL

利用Django数据库游标的mogrify方法,自动生成符合数据库语法的参数化语句:

from django.db import connection

with connection.cursor() as cursor:
    # 生成占位符
    placeholders = ", ".join(["%s"] * len(list_of_uuids))
    # mogrify会将参数转换为数据库兼容的格式
    sql = cursor.mogrify(
        f"SELECT * FROM some_model_table WHERE some_model_table.uuid IN ({placeholders})",
        list_of_uuids
    ).decode()
# 执行原生查询
query_set = SomeModel.objects.raw(sql)

这种方式能确保SQL格式完全适配当前数据库,同时避免注入风险。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 09:40:47