merge querysets in django
14,848
Solution 1
This should do the trick:
# On the top of the file:
from django.db.models import Q
# Game instance method:
def get_all_players(self):
return Player.objects.filter(Q(games1__pk=self.pk) | Q(games2__pk=self.pk))
Q
is described in details here: Complex lookups with Q objects.
Solution 2
For a perhaps more semantically clear solution:
def get_all_players(self):
return (self.players1.all() | self.players2.all()).distinct()
Author by
imkost
Updated on June 04, 2022Comments
-
imkost almost 2 years
I have in
models.py
:class Game(models.Model): players1 = models.ManyToManyField(Player, related_name='games1') players2 = models.ManyToManyField(Player, related_name='games2') def get_all_players(self): return list(itertools.chain(self.players1.all(), self.players2.all()))
How can I write same
get_all_players
method, but returnQuerySet
, notlist
?P.S. I know that there is | operator:
def get_all_players(self): return self.players1.all() | self.players2.all()
But it works in a very strange way. Result of this function contains more players than there are in players1 + players2 (result contains repeats of some players)
-
imkost over 11 yearsThank you very much! I didn't know that
games1
inQ
will iterate all games. Tell me, why do you usegames1__pk=self.pk
instead ofgames1=self
? Are there any advantages in this way? -
Tadeck over 11 years@imkost: I am just used to it. I believe
games1=self
may be implicitly translated togames1__pk=self.pk
(if it gives you the same result). Having__
in the argument name also makes it clear that there are someJOIN
s involved in the query. -
Kye over 7 yearsThis is definitely the more clean solution.