web-dev-qa-db-fra.com

Django filtrer le modèle sur le nombre ManyToMany?

Supposons que j'ai quelque chose comme ça dans mes 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")

Maintenant, dans mon views.py, je voudrais faire une requête qui chercherait une partie pour l'utilisateur où il y a plus de 0 participants.

Quelque chose comme ça peut-être:

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

Quelle est la meilleure façon de procéder?

65
Ska

Si cela fonctionne, c'est comme ça que je le ferais.

La meilleure façon peut signifier beaucoup de choses: meilleures performances, plus maintenables, etc. Par conséquent, je ne dirai pas que c'est la meilleure façon, mais j'aime m'en tenir aux fonctionnalités ORM autant que possible car elles semblent plus maintenables.

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))
107
solartic
Party.objects.filter(organizer=user, participants__isnull=False)
Party.objects.filter(organizer=user, participants=None)
31

Plus simple avec exclude:

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

Retourne également des résultats distincts

5
Arseniy Panfilov

Dérivé de la réponse @ Yuji-'Tomita'-Tomita, j'ai également ajouté .distinct ('id') pour exclure les enregistrements en double:

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

Par conséquent, chaque partie n'est répertoriée qu'une seule fois.

1
Kostyantyn