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

Django Rest Framework中按用户名和显示名搜索用户的问题

解决Django Rest Framework中用户搜索的子串匹配问题

你当前用istartswith实现的是前缀匹配,只能匹配字段开头的子串,所以会出现这些问题:

  • 显示名William Welch里的Welch不是字段开头,搜索时无法命中
  • 用户名123William里的23w、elch这类中间子串也匹配不到

下面给出两种可行解决方案:

方案1:改用icontains实现全子串匹配

直接把istartswith替换成icontains,就能匹配字段中任意位置的子串,且忽略大小写:

search_obj = User.objects.exclude(user_uuid=token_user_uuid).filter(
    Q(display_name__icontains=search_name) 
    | Q(username__icontains=search_name)
).order_by('-created_on')[:10]

效果验证

针对你的测试案例,该方案能全部命中:

  • search_name=12 → 匹配123William的前缀部分
  • search_name=23w → 匹配123William的中间子串
  • search_name=Wil → 匹配William Welch和123William
  • search_name=Welc → 匹配William Welch中的Welch前缀
  • search_name=elch → 匹配William Welch中的Welch中间子串

性能提示

如果用户表数据量较大,icontains可能拉低查询速度。可以给username和display_name字段加数据库索引优化:

  • PostgreSQL:创建gin或gist类型索引
  • MySQL:使用fulltext索引(配合search查询更高效)

方案2:按词语前缀匹配(精准场景)

如果希望仅匹配显示名中独立词语的前缀(比如Welch是独立词能命中,但不会误匹配WilliamWelch这种连写的中间子串),可以用iregex实现正则匹配:

import re

# 转义搜索关键词里的特殊字符,避免正则报错
escaped_search = re.escape(search_name)
# 正则规则:匹配任意独立单词以搜索词开头(\b是单词边界)
regex_pattern = rf'\b{escaped_search}'

search_obj = User.objects.exclude(user_uuid=token_user_uuid).filter(
    Q(display_name__iregex=regex_pattern)
    | Q(username__icontains=search_name)  # 用户名可按需改为regex规则
).order_by('-created_on')[:10]

适用场景

适合用户显示名是全名的场景,搜索姓氏时能精准匹配,不会误匹配到名字中间的相似子串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 08:06:04