Django对ManyToMany计数模型?


72

假设我的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)

最好的方法是什么?

Answers:


123

如果这可行,这就是我会做的。

最佳方法可能意味着很多事情:最佳性能,最可维护等。因此,我不会说这是最佳方法,但是由于它似乎更具可维护性,因此我希望尽可能地坚持使用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))

这是另一种好方法,尽管不如所选择的答案那么简洁。
詹森(Jathanism)2011年

11
+1,“大于Y”,“小于X”都在这里涵盖,而不仅仅是null,它实际上回答了问题:“ Django在ManyToMany计数上过滤模型”
Skylar Saveland 2012年

这比OP总结的问题更好地回答了OP的总结问题,而不仅仅是要在零相关实例上进行过滤的情况。
伊恩·克拉克

3
@gregoltsov 5年后,这现在公认的答案:)
Ska

32
Party.objects.filter(organizer=user, participants__isnull=False)
Party.objects.filter(organizer=user, participants=None)

我认为这不是最优雅的解决方案,但对我而言有效。如果有任何明智的方法,我仍然会四处看看。
Ska

这个解决方案有什么不好的地方?这正是您要的!:)答案尚不完全清楚,但是您可以使用其中之一,而不能同时使用两者。解决同一问题的两种方法。
贾森主义

1
@Ska但这正是我的解决方案。它允许您指定实际数值。
solartic'11年

2
@Yuji,当我这样做时,“ participants__isnull = False”将导致重复的条目。你有什么主意吗?
Crossin

1
@crossin(如果查询可能导致重复),请附加.distinct()到查询中。
Yuji'Tomita'Tomita


3

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.