kissgyorgy
kissgyorgy

Reputation: 3010

How to get django model by ManyToMany relationship?

I got a list of Player instances (a team) for example team = [player1, player2, player3]

How do I "get_or_create" the Team containing these and only these three players with one query?

These are my django models:

class Player(models.Model):
    name = models.CharField(max_length=100)

class Team(models.Model):
    players = models.ManyToManyField(Player)

Upvotes: 2

Views: 168

Answers (1)

Adrián
Adrián

Reputation: 6255

Documentation says that get_or_create is a shortcut for:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()

So I would adapt it to your use case as follows:

from django.db.models import Q, Count
import operator

players = [player1, player2, player3]

team = Team.objects
    .filter(reduce(
         operator.and_,
         [Q(players=player) for player in players]
    ))
    .annotate(count=Count('players'))
    .filter(count=len(players))

# Note that this ^ returns a QuerySet. With your posted model there
# might exist several teams with exactly the same players.  

if not team.exists():
    team = Team.objects.create()
    team.players.add(*players)

Slightly more complex but the workflow is the same:

  • Query for existence.
  • If not existent, create.

Upvotes: 1

Related Questions