Django如何过滤嵌套多对多字段,获取所有关联Message均无Label的Thread
需求说明
现有Django模型定义如下:
class Label(models.Model): name = CharField() class Message(models.Model): labels = ManyToManyField(Label) class Thread(models.Model): messages = ManyToManyField(Message)
需要筛选出所有关联Message都未绑定任何Label的Thread对象,原查询Thread.objects.filter(messages__labels__isnull=True)仅匹配存在任意一条Message无Label的Thread,不符合要求。
解决方案
方案1:反向排除法(最简洁,性能最优)
直接排除「存在至少一条Message绑定了Label」的Thread,剩余结果即为符合要求的对象:
Thread.objects.exclude(messages__labels__isnull=False)
方案2:计数校验法(更直观,适合需要同步统计数据的场景)
通过聚合统计每个Thread关联的Label总数量,筛选数量为0的结果:
from django.db.models import Count Thread.objects.annotate( labeled_msg_count=Count('messages__labels') ).filter(labeled_msg_count=0)
补充说明
如果需要排除没有关联任何Message的空Thread,可以在过滤条件中额外增加messages__isnull=False:
# 方案1补充过滤空Thread Thread.objects.exclude(messages__labels__isnull=False).filter(messages__isnull=False) # 方案2补充过滤空Thread from django.db.models import Count Thread.objects.annotate( labeled_msg_count=Count('messages__labels'), msg_count=Count('messages') ).filter(labeled_msg_count=0, msg_count__gt=0)
内容的提问来源于stack exchange,提问作者Arun
相关产品推荐
相关产品推荐

