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

如何在Django中按ID分组获取首个非空组织字段的QuerySet

解决Django QuerySet按ID获取首个非空Organisation的问题

没问题,我来帮你搞定这个需求!你想要的是按id分组,每个id保留第一个非空的organisation值,如果某个id对应的所有organisation都是空的,就保留None。这里有几种实用的实现方式,你可以根据数据量和场景选择:

方法一:数据库层面处理(推荐,效率更高)

直接用Django ORM的聚合函数和条件判断,在数据库层面完成筛选,适合数据量大的场景:

from django.db.models import Case, When, Value, F
from django.db import models

# 替换成你的实际模型类名
result = YourModel.objects.annotate(
    # 给每条记录标记非空的organisation,空的则设为None
    non_empty_org=Case(
        When(organisation__isnull=False, then=F('organisation')),
        default=Value(None),
        output_field=models.CharField()  # 这里要匹配你的organisation字段类型,比如models.TextField()
    )
).order_by('id', '-non_empty_org').distinct('id')

逻辑说明:

  1. annotate给每条记录添加一个临时字段non_empty_org,非空的organisation会保留原值,空的则为None;
  2. order_by('id', '-non_empty_org')先按id分组排序,同时把有非空organisation的记录排在同id的最前面;
  3. distinct('id')会保留每个id的第一条记录,也就是优先拿到非空的organisation,如果没有则保留None。

方法二:拆分QuerySet合并

如果觉得上面的写法有点复杂,可以分两步筛选再合并:

# 第一步:获取所有存在非空organisation的id对应的第一条记录
non_empty_records = YourModel.objects.filter(organisation__isnull=False).distinct('id')

# 第二步:获取那些所有organisation都是空的id对应的记录
null_only_ids = YourModel.objects.values_list('id', flat=True).exclude(
    id__in=non_empty_records.values_list('id', flat=True)
)
null_only_records = YourModel.objects.filter(id__in=null_only_ids).distinct('id')

# 合并两个QuerySet
result = non_empty_records | null_only_records

方法三:Python层面处理(适合小数据量)

如果你的数据量不大,也可以在Python内存中处理,逻辑更直观:

from collections import OrderedDict

# 获取原始QuerySet
queryset = YourModel.objects.all()
# 用OrderedDict来保证顺序,同时去重
unique_entries = OrderedDict()

for item in queryset:
    if item.id not in unique_entries:
        # 第一次遇到这个id,直接存入
        unique_entries[item.id] = item
    else:
        # 如果之前存入的该id记录organisation是空的,现在这个非空,就替换
        if unique_entries[item.id].organisation is None and item.organisation is not None:
            unique_entries[item.id] = item

# 最终结果可以转成列表,或者再转回QuerySet
final_result = list(unique_entries.values())
# 如果需要QuerySet格式:
# final_result = YourModel.objects.filter(id__in=unique_entries.keys()).order_by('id')

小结

如果数据量较大,优先选方法一,因为数据库层面的处理比Python内存处理效率高很多;小数据量的话,方法三的逻辑更易懂,调试起来也方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:33:11