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

如何使用字段子串为Django QuerySet添加注解?

从字段子串生成Django QuerySet注解的实现方法

你提供的代码思路没问题,但存在一个关键错误:Django的F对象并没有Index()方法,直接调用会报错。要实现从email字段提取域名并添加注解,需要借助Django内置的数据库函数来定位字符位置,以下是正确的实现方式:

通用数据库兼容方案

先导入所需的函数:

from django.db.models import Count, F
from django.db.models.functions import Substr, StrIndex

然后构建QuerySet:

query_by_domain = (
    queryset
    # 标注@符号在email中的位置
    .annotate(at_position=StrIndex(F('email'), '@'))
    # 从@的下一位开始截取,得到域名
    .annotate(domain=Substr(F('email'), F('at_position') + 1))
    # 过滤掉无@的无效邮箱(可选)
    .filter(at_position__gt=0)
    # 按域名分组
    .values('domain')
    # 统计每组记录数
    .annotate(count=Count('id'))
    # 按域名排序
    .order_by('domain')
)

PostgreSQL专属简化方案

如果你的项目基于PostgreSQL数据库,可以用SplitPart函数直接分割字符串,代码更简洁:

from django.db.models import Count, F
from django.db.models.functions import SplitPart

query_by_domain = (
    queryset
    # 按@分割email,取第2部分作为域名
    .annotate(domain=SplitPart(F('email'), '@', 2))
    .filter(domain__ne='')
    .values('domain')
    .annotate(count=Count('id'))
    .order_by('domain')
)

关键说明

  • StrIndex返回指定字符在字符串中的位置(从1开始计数),找不到则返回0,因此可以通过filter(at_position__gt=0)过滤格式无效的邮箱。
  • Substr的参数为:源字段、起始位置、截取长度(可选,不填则截取到字符串末尾)。
  • SplitPart的参数为:源字段、分隔符、要提取的分割部分序号(从1开始计数)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:40:23