2013-01-07 104 views
7

我在models.py合并查询集在Django

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())) 

我怎么能写相同get_all_players方法,但返回QuerySet,不list

P.S.我知道有| |运营商:

def get_all_players(self): 
    return self.players1.all() | self.players2.all() 

但它工作在一个非常奇怪的方式。这个函数的结果包含更多的玩家以外还有players1 + players2(结果中包含的一些玩家重复)

回答

10

这应该做的伎俩:

# 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在这里详细描述:Complex lookups with Q objects

+0

非常感谢您!我不知道'Q'中的'games1'会迭代所有游戏。告诉我,为什么你用'games1__pk = self.pk'而不是'games1 = self'?这样有什么好处吗? – imkost

+0

@imkost:我已经习惯了。我相信'games1 = self'可能会隐式转换为'games1__pk = self.pk'(如果它给出了相同的结果)。在参数名称中有'__'还表明查询中涉及一些'JOIN'。 – Tadeck

11

对于一个或许更语义明确的解决方案:

def get_all_players(self): 
    return (self.players1.all() | self.players2.all()).distinct() 
+2

这绝对是更干净的解决方案。 –