【问题标题】:How do you do multiple joins simultaneously in Django ORM?如何在 Django ORM 中同时进行多个连接?
【发布时间】:2018-07-17 11:18:58
【问题描述】:

给定一堆图形地图,我需要查询用户可以访问哪些地图,要么是因为他拥有地图,要么是因为他已获得地图的“会员资格”。

有一个 Map_desc(地图描述)模型,对于 Map_desc 中的每个对象,可能有许多 Mapmembership 对象。

因为它稍后将被提供给模板中的 ModelChoiceFields,所以我需要一个 QuerySet 来返回所有具有相关 Mapmembership 对象的 Map_desc 对象,以及所有将“所有者”设置为当前用户的 Map_desc 对象。

这是一个简单的连接,但在 Django 中很难实现。

models.py(简化版)

class Map_desc(models.Model):
  owner = models.ForeignKey(User, null=False, on_delete=models.CASCADE)

class Mapmember(models.Model):
  member = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
  ofmap = models.ForeignKey(Map_desc, null=False, on_delete=models.CASCADE)

我首先尝试的没有工作(在半伪代码中):

shared = Map_desc.objects.filter(id=mapmember_set.ofmap)

然后进行第二次查询以获取所拥有的地图:

owned = Map_desc.objects.filter(owner=thisUser)

并将它们捆绑在一起

accessiblemaps = chain(shared,owned)

问题是因为有多个 Map_desc 对象,所以 mapmember_set 实际上是不可用的。如果您使用 .first() 将查询限制为仅一个 Map_desc,它确实有效,这就是我发现的所有教程和 SO 问题的作用。

所以我想出了以下解决方案,它确实有效,但我想知道是否有更有效的方法,或者只是不同的方法可以帮助我理解 ORM 的意义用于涉及多个“父对象”行的联接。

views.py

from django.db.models import Q

def all_accessible_maps(request, thisUser):
  # Returns maps thisUser has access to, whether owned or as a 'member'
  try:
    sharedmaps = Mapmember.objects.filter(member=thisUser).values_list('ofmap')
    allaccessible = Map_desc.objects.filter(Q(id__in=sharedmaps) | Q(owner=thisUser))    
  except:
    raise

all_accessible_maps.alters_data = True

【问题讨论】:

  • 看起来您可以使用 ManyToManyField 来表示成员关系

标签: python django join


【解决方案1】:

您可以添加Q(mapmember__member=thisUser)__ 将与Mapmember 表连接:

Map_desc.objects.filter(Q(owner=thisUser) | Q(mapmember__member=thisUser))

【讨论】:

  • 如果我理解正确,您可以拥有一张地图,而无需成为任何地图的成员。在这种情况下,您会错过一些条目
  • @BenjaminToueg hm.. 我认为它也应该适用于这种情况。查询其中任何一个有或条件并返回记录。
  • 再想一想,我很确定它不会起作用。如果您认为我错了,请详细说明
  • @BenjaminToueg 哦,我知道我选择了 Mapmember 而不是 Map_desc。新版本应该可以工作。
  • 这有效,并保存了一个查询。我已经接受它作为答案。谢谢@neverwalkaloner。由于“mapmember”是一个单独的表,因此仍然很难想象它是如何工作的,但查询返回 Map_desc 表对象。查询中没有明确提及它们之间的共享键。我习惯于在两个表之间的连接中想象空值。
猜你喜欢
  • 2018-01-10
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 2014-06-19
  • 1970-01-01
  • 2018-04-08
  • 2010-10-13
  • 1970-01-01
相关资源
最近更新 更多