如何通过多对多关系获取 django 模型?

Posted

技术标签:

【中文标题】如何通过多对多关系获取 django 模型?【英文标题】:How to get django model by ManyToMany relationship? 【发布时间】:2013-07-04 18:46:12 【问题描述】:

我得到了Player 实例(一个团队)的列表,例如team = [player1, player2, player3]

我如何通过一个查询“get_or_create”包含这些且只有这三个玩家的Team

这些是我的 django 模型:

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

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

【问题讨论】:

这个答案应该让你回到正轨***.com/questions/5301996/django-many-to-many-query 我现在正在寻找答案,但我可能需要一段时间才能真正发布它。 你知道即使你只需要打电话给get_or_create 也需要2个查询吗? 【参考方案1】:

文档说get_or_create 是一个快捷方式:

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

所以我会根据您的用例进行如下调整:

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)

稍微复杂一点,但工作流程是一样的:

查询是否存在。 如果不存在,则创建。

【讨论】:

我接受了你的回答,但是我发现了一个小错误。 team.players.add() 不接受可迭代的但有多个参数,所以它应该是 team.players.add(*players) 使用 python 的 unpacking feature。看到它in django documentation。

以上是关于如何通过多对多关系获取 django 模型?的主要内容,如果未能解决你的问题,请参考以下文章

如何使通过多对多关系连接的模型在 Django admin 中同时在两个地方可编辑?

如何通过多对多字段(精确匹配)中的对象过滤 django 模型?

如何在双连接关系之后在 Django 中执行查询(或:如何绕过 Django 对多对多“通过”模型的限制?)

ObjectionJs 获取具有多对多关系的实体

在 django 中获取具有多对多关系的复杂查询集

如何以 django 形式过滤多对多字段