Django在ManyToMany计数上过滤模型?

Posted

技术标签:

【中文标题】Django在ManyToMany计数上过滤模型?【英文标题】:Django filter the model on ManyToMany count? 【发布时间】:2011-12-14 14:19:39 【问题描述】:

假设我的 models.py 中有这样的东西:

class Hipster(models.Model):
  name = CharField(max_length=50)

class Party(models.Model):
  organiser = models.ForeignKey()
  participants = models.ManyToManyField(Profile, related_name="participants")

现在在我的 views.py 中,我想做一个查询,为参与者超过 0 人的用户获取派对。

可能是这样的:

user = Hipster.get(pk=1) 
hip_parties = Party.objects.filter(organiser=user, len(participants) > 0)

最好的方法是什么?

【问题讨论】:

【参考方案1】:

如果这行得通,我会这样做。

最好的方式可能意味着很多事情:最好的性能、最易维护等。因此我不会说这是最好的方式,但我喜欢尽可能地坚持 ORM 的特性,因为它看起来更易于维护。

from django.db.models import Count

user = Hipster.objects.get(pk=1) 
hip_parties = (Party.objects.annotate(num_participants=Count('participants'))
                            .filter(organiser=user, num_participants__gt=0))

【讨论】:

这是另一种好方法,尽管不如所选答案简洁。 +1, "more than Y", "less than X" 都在这里涵盖,而不仅仅是 null 实际回答了问题,“Django filter the model on ManyToMany count” 这比接受的答案更好地回答了 OPs 总结的问题,而不仅仅是您想要过滤零相关实例的情况。 @gregoltsov 5 年后,这现在被接受的答案:)【参考方案2】:
Party.objects.filter(organizer=user, participants__isnull=False)
Party.objects.filter(organizer=user, participants=None)

【讨论】:

我不认为这是最优雅的解决方案,但它适用于我的情况。如果有任何理智的方法,我仍然会环顾四周。 这个解决方案有什么不优雅的地方?这正是你所要求的! :) 答案并不完全清楚,但你会使用其中一个,而不是两者都使用。解决同一问题的两种方法。 @Ska 但这正是我的解决方案所做的。它允许您指定实际的数值。 @Yuji,当我这样做时,“participants__isnull=False”将导致重复条目。你有什么想法吗? @crossin 如果查询可能导致重复,请将.distinct() 附加到您的查询中。【参考方案3】:

exclude 更容易:

# organized by user and has more than 0 participants
Party.objects.filter(organizer=user).exclude(participants=None)

也返回不同的结果

【讨论】:

【参考方案4】:

源自@Yuji-'Tomita'-Tomita 答案,我还添加了 .distinct('id') 以排除重复记录:

Party.objects.filter(organizer=user, participants__isnull=False).distinct('id')

因此,每一方只列出一次。

【讨论】:

以上是关于Django在ManyToMany计数上过滤模型?的主要内容,如果未能解决你的问题,请参考以下文章

Django:ManyToMany过滤器匹配列表中的所有项目

django - manytomany 上的查询过滤器为空

Django DRF视图过滤ManyToMany查询集

Django:模型设计,ManyToMany 属性字段?

Django 模型 ManytoMany getter

当嵌套序列化程序中有另一个模型(manytomany)时,如何在 django 模型上发布,我想同时创建两者