【问题标题】:How to use Q objects to check if any members of arbitrary-length list are in Many-To-Many Relationship?如何使用 Q 对象检查任意长度列表的任何成员是否处于多对多关系?
【发布时间】:2013-06-02 17:48:27
【问题描述】:

假设我有以下 Django 模型:

class myClass1(models.Model):
    myField1 = models.IntegerField()     


class myClass2(models.Model):
    myLocalClass1 = models.ManyToManyField(myClass1)     

此外,假设我有一个唯一的 myClass1 列表:

a = myClass1(myField=1)
b = myClass1(myField=2)
c = myClass1(myField=3)
myTargetList = [a, b, c]

现在,我想使用 Q 对象编写一个 Django 查询,以便它返回所有具有 myTargetList 的任何成员作为 myLocalClass1 的 myClass2。此外,我事先不知道 myTargetList 的确切大小。

我该怎么做?这显然行不通:

myClass2.objects.filter(Q(myLocalClass1__in=myTargetList))

【问题讨论】:

  • myClass2.objects.filter(myLocalClass1__in=myTargetList) 将起作用(假设那些具有 ID 并保存到数据库中)。如果不是这个,你的问题是什么?您是否正在寻找与 myTargetList 中的项目完全相同的 myClass2 对象?

标签: django django-models django-q


【解决方案1】:

你可以这样做:

myclass1_qs = myClass1.objects.filter(myField__in=[1, 2, 3])
myclass2_qs = myClass2.objects.filter(myLocalClass1__in=myclass1_qs).distinct()

或者这是一个单行,

myclass2_qs = myClass2.objects.filter(myLocalClass1__myField__in=[1, 2, 3]).distinct() 

【讨论】:

  • 这很优雅....而且几乎可以工作。问题是 myclass2_qs 现在包含所有符合条件的 MyClass2。但是,对于链接到多个 myClass1 的那些 MyClass2,它包含重复的 MyClass2。如何确保 myclass2_qs 不包含重复项?当然,我可以在 python 中做到这一点。但是,如果数据库层在将答案传回给我之前这样做,那将是最有效的。对吗?
  • 你需要在查询集中使用.distinct()子句。
【解决方案2】:

你几乎拥有它,你不需要Q对象,你可以使用invalues_list的组合:

l = myClass1.objects.filter(myField__in=[1, 2, 3]).values_list("id", flat=True)
myClass2.objects.filter(myLocalClass1__pk__in=l) 

【讨论】:

  • 不,我不认为这是正确的。在这种情况下,您的列表 l 将是 myTargetList 中所有 myClass1 的 id 列表。因此在这些 id 上过滤 myClass2 是没有意义的。我们如何将 myClass1 id 列表翻译成正确的 myClass2 id 列表?
  • 您想获取列表中至少包含myClass1 对象之一的所有myClass2 对象,对吗?
  • 是的。但我不相信这就是你的解决方案的作用。您的解决方案会获取我感兴趣的 myClass1 的 ID 列表。然后它会查找与这些 ID 匹配的 myClass2。这是不对的(除非我真的错过了一些非常重要的东西。但我不认为我是)
  • 啊,好吧,抱歉,它的错字应该是 myLocalClass1__pk__in 而不是 pk__in
  • 这已经在第一个查询中处理过了。使用 pks 搜索的原因是您不必加入表(尽管我认为 orm 在内部无论如何都会这样做)
猜你喜欢
  • 2013-06-01
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 2017-09-23
  • 1970-01-01
  • 1970-01-01
  • 2017-10-16
相关资源
最近更新 更多