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 return QuerySet
, not list
?
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)
You can also use the chain() method from the Itertools module, which allows you to combine two or more QuerySets from different models through concatenation. Alternatively, you can use union() to combine two or more QuerySets from different models, passing all=TRUE if you want to allow duplicates.
Use union operator for queryset | to take union of two queryset. If both queryset belongs to same model / single model than it is possible to combine querysets by using union operator. One other way to achieve combine operation between two queryset is to use itertools chain function.
Join can be done with select_related method: Django defines this function as Returns a QuerySet that will “follow” foreign-key relationships, selecting additional related-object data when it executes its query.
Django Q is a native Django task queue, scheduler and worker application using Python multiprocessing.
For a perhaps more semantically clear solution:
def get_all_players(self):
return (self.players1.all() | self.players2.all()).distinct()
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With