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

如何在Django ORM中不对'%'字符进行转义?

问题描述

使用Django ORM开发时,希望查询时不对字符%进行转义,但当前使用__contains生成的SQL会自动转义%为\%,不符合需求。

当前代码:

name=''
author=''
annotation = 'harry%magic%school'

criterion_name = Q(name__contains=cleaned_data['name'])
criterion_author = Q(author__contains=cleaned_data['author'])
criterion_annotation = Q(annotation__contains=cleaned_data['annotation'])

Book.objects.filter(criterion_name, criterion_author, criterion_annotation)

生成的SQL(不符合预期):

select name, author, annotation from books 
where name LIKE '%%' AND 
author LIKE '%%' AND 
annotation LIKE '%harry\%magic\%school%'

期望生成的SQL:

select name, author, annotation from books 
where name LIKE '%%' AND 
author LIKE '%%' AND 
annotation LIKE '%harry%magic%school%'
解决方法

Django的__contains会自动转义%和_(LIKE语法的通配符),把它们当作普通字符处理。如果你要让输入的%作为LIKE的通配符使用,有以下几种可行方案:

方案1:使用RawSQL直接构造LIKE条件

直接用RawSQL手动拼接LIKE语句,跳过Django的自动转义:

from django.db.models import RawSQL

# 构造完整的LIKE匹配串,保留输入中的%作为通配符
annotation_pattern = f"%{cleaned_data['annotation']}%"

Book.objects.filter(
    criterion_name,
    criterion_author,
    RawSQL("annotation LIKE %s", [annotation_pattern])
)

方案2:自定义Func实现LIKE查询

通过自定义Func类来构建未转义的LIKE表达式,更符合ORM的使用习惯:

from django.db.models import Func, Value

class Like(Func):
    function = 'LIKE'
    template = "%(expressions)s %(function)s %(pattern)s"

# 生成查询条件
criterion_annotation = Like('annotation', Value(f"%{cleaned_data['annotation']}%"))

Book.objects.filter(criterion_name, criterion_author, criterion_annotation)

方案3:改用正则表达式查询(__regex)

如果可以接受用正则表达式替代LIKE,把输入中的%替换成正则的通配符.*:

# 将输入中的%替换为正则的任意字符匹配
regex_pattern = cleaned_data['annotation'].replace('%', '.*')
criterion_annotation = Q(annotation__regex=regex_pattern)

Book.objects.filter(criterion_name, criterion_author, criterion_annotation)

注意:这种方式生成的是REGEXP/RLIKE语句,和LIKE的匹配逻辑略有差异,性能也可能不同,需根据场景选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 15:15:16