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

Django中icontains无法检索富文本字段内的加粗内容

问题分析与解决方案

问题核心在于CKEditor富文本字段的存储特性:数据库中存储的是带HTML标签的内容(比如<strong>arbitration</strong> <strong>agreement</strong>),而用户复制的加粗文本是连续纯文本(arbitration agreement),此时icontains无法匹配被标签拆分的内容;或者用户复制时不小心带上HTML标签,导致搜索词与数据库内容不匹配。


方案1:实时清理搜索词+处理富文本字段查询

直接在搜索逻辑中清理用户输入,并对富文本字段去除HTML标签后再查询(以下为PostgreSQL适配代码,其他数据库需调整正则处理函数):

import re
from django.db.models import Func, Value
from rest_framework.response import Response
from rest_framework import status

def search_citation(request):
    q = request.data.get('q', '')
    
    # 清理搜索词:移除HTML标签、合并多余空格、去除首尾空白
    def clean_query(query):
        query = re.sub(r'<.*?>', '', query)  # 移除所有HTML标签
        query = re.sub(r'\s+', ' ', query)   # 把多空格/换行换成单个空格
        return query.strip()
    
    q = clean_query(q)
    
    if len(q) > 78 or len(q) < 1:
        return Response({"message":'not appropriate'}, status=status.HTTP_200_OK)
    
    try:
        # 常规字段查询保持不变
        judge_name = Civil.objects.filter(judge_name__icontains=q)
        case_no = Civil.objects.filter(case_no__icontains=q)
        party_name = Civil.objects.filter(party_name__icontains=q)
        advocate_petitioner = Civil.objects.filter(advocate_petitioner__icontains=q)
        advocate_respondent = Civil.objects.filter(advocate_respondent__icontains=q)
        institution_name = Civil.objects.filter(institution_name__icontains=q)
        title = Civil.objects.filter(title__icontains=q)
        sub_law_type = Civil.objects.filter(sub_law_type__icontains=q)
        law_category = Civil.objects.filter(law_category__icontains=q)
        
        # 自定义函数:移除HTML标签(PostgreSQL专用)
        class StripHTML(Func):
            function = 'REGEXP_REPLACE'
            template = "%(function)s(%(expressions)s, '<.*?>', '', 'g')"
        
        # 对富文本字段先转纯文本再查询
        judgements = Civil.objects.annotate(
            plain_judgements=StripHTML('judgements')
        ).filter(plain_judgements__icontains=q)
        
        # 合并查询集并去重,避免重复结果
        q_final = (judge_name | case_no | party_name | advocate_petitioner | 
                   advocate_respondent | title | sub_law_type | law_category | 
                   judgements | institution_name).distinct()
        
        q_serial = Initial_Detail_Serial(q_final, many=True)
        return Response(q_serial.data, status=status.HTTP_200_OK)
        
    except Exception as e:
        print(e)
        return Response({"error":str(e)}, status=status.HTTP_400_BAD_REQUEST)

方案2:新增纯文本字段同步存储(性能更优)

如果搜索频率高,建议在模型中添加纯文本字段,保存富文本时自动同步纯文本内容,避免每次查询都处理HTML:

1. 修改模型

# models.py
from django.db import models
from ckeditor.fields import RichTextField
import re

def strip_html(html_content):
    # 移除HTML标签并清理空白
    return re.sub(r'<.*?>', '', html_content).strip()

class Civil(models.Model):
    # 原有富文本字段
    judgements = RichTextField()
    # 新增纯文本字段,自动生成,不允许手动编辑
    judgements_plain = models.TextField(blank=True, editable=False)
    
    def save(self, *args, **kwargs):
        # 保存时自动生成纯文本内容
        self.judgements_plain = strip_html(self.judgements)
        super().save(*args, **kwargs)

2. 批量更新已有数据

对已存在的记录,需批量生成纯文本内容(可在Django shell中执行):

from your_app.models import Civil

for obj in Civil.objects.all():
    obj.save()  # 触发save方法自动生成judgements_plain

3. 修改搜索逻辑

直接查询纯文本字段即可:

# views.py中替换judgements的查询
judgements = Civil.objects.filter(judgements_plain__icontains=q)

关键提示

  • 方案1适合快速修复,无需修改模型,但性能略差;方案2性能更优,适合频繁搜索的场景。
  • 必须添加distinct(),避免同一记录被多个过滤条件重复匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 06:06:31