在Django中过滤具有相同M2M关系的不同项目

时间:2017-03-03 08:01:11

标签: django django-models django-queryset

我创建了一些用于在联盟中注册游戏的Django模型。有点简化,这就是它的样子。

class Participant(models.Model):
    first_name = models.CharField(u"First name", max_length=50)
    last_name = models.CharField(u"Last name", max_length=50)


class Match(models.Model):
    players = models.ManyToManyField(Participant)

我决定通过M2M关联这些模型,因为我想轻松查询包含某个参与者的游戏,如果我选择使用"player_one""player_two"两个字段,这会感觉很麻烦。这也使得系统在添加具有两个以上参与者的游戏方面具有一定的灵活性。

无论如何,一些联赛将允许两个玩家不止一次面对面,并且它还允许一些自由形式的调度,这意味着一个玩家可以玩20个游戏,而另一个玩家只玩了8个。

问:我如何制作一个查询,让我过滤掉只包含唯一比赛的所有比赛? I. e。 Jen已经打了12场比赛,但其中有三场是对阵保罗,而我只想数其中一个得到她所面对的所有独特对手的名单。

1 个答案:

答案 0 :(得分:0)

注意:可能这个解决方案效率不高,我相信还有更好的解决方案。

如果您可以更改模型结构,则可以向unique_matches模型添加另一个字段Participant

class Participant(models.Model):
    first_name = models.CharField(u"First name", max_length=50)
    last_name = models.CharField(u"Last name", max_length=50)
    unique_matches = models.ManyToManyField(Match)

然后,当您需要创建新的Match记录时,可以检查if did these players played against eachother before?。并根据以下内容更新unique_matches字段:

# assume request.user is jen right now
paul = Participant.objects.get(id=3)
if not paul in request.user.unique_matches.all():
    request.user.unique_matches.add(paul)

您可以在创建每条Match条记录后进行此控制。

稍后,如果您查询如下:

matches = request.user.unique_matches.all()

这会给你独特的对决。

第二种解决方案

如果你想保留现有的模型结构,可以尝试这样的事情(实际上这可能是一种更好的方法):

class Participant(models.Model):
    first_name = models.CharField(u"First name", max_length=50)
    last_name = models.CharField(u"Last name", max_length=50)


    def unique_matches(self):
        matches = self.match_set.all()
        uniques = []
        for match in matches:
            for player in match.players.all():
                if (player.pk != self.pk) and (not player in uniques):
                    uniques.append(player)

        return uniques

然后您可以在以下任何地方使用此方法:

matches = request.user.unique_matches()

我没有测试这些解决方案。如果发生任何错误,请告诉我,我们可以尝试解决这个问题。