【问题标题】:How to do an OR on a Django ManyToManyField without getting duplicates?如何在不重复的情况下对 Django ManyToManyField 进行 OR?
【发布时间】:2017-01-23 01:32:24
【问题描述】:

我有以下两个 Django 类 MyClassAMyClassB

MyClassB 有一个多对多字段MyClassAs

from django.db import models

class MyClassA(models.Model):
    name = models.CharField(max_length=50, null=False)

    def __str__(self):
        return "<%s %s>" % (
        self.__class__.__name__, "; ".join(["ID: %s" % self.pk, "name: %s" % self.name, ]))

class MyClassB(models.Model):
    name = models.CharField(max_length=50, null=False)
    my_class_as = models.ManyToManyField(MyClassA, related_name="MyClassB_my_class_as")

    def __str__(self):
        return "<%s %s>" % (
        self.__class__.__name__, "; ".join(["ID: %s" % self.pk, "name: %s" % self.name, ]))

然后我使用以下数据为数据库播种:

>>> a = MyClassA.objects.create(name="A")
>>> b = MyClassA.objects.create(name="B")
>>> c = MyClassA.objects.create(name="C")
>>> d = MyClassA.objects.create(name="D")
>>> e = MyClassA.objects.create(name="E")
>>> u = MyClassB.objects.create(name="U")
>>> u.my_class_as.add(c)
>>> u.my_class_as.add(d)
>>> u.save()

我想查找与 MyClassA 的实例 cd 有关系的 MyClassB 的(唯一)列表。我该怎么做??

我的解决方案是在MyClassB 上创建以下静态方法:

@staticmethod
def is_m2m_related_queryset(my_class_a_list):
    q = Q()
    for curr_a in my_class_a_list:
        q |= Q(my_class_as=curr_a)
    return q

...然后运行以下查询:

>>> MyClassB.objects.filter(MyClassB.is_m2m_related_queryset([c, d]))
[<MyClassB: <MyClassB ID: 11; name: U>>, <MyClassB: <MyClassB ID: 11; name: U>>]

但是等等! 这个查询集没有像我预期的那样返回一个包含u 对象的单例列表,而是返回[u, u]。那不是我想要的。 这不应该返回[u]吗? 为什么它会返回它所做的事情?

我应该如何得到我想要的?我应该简单地将.distinct() 附加到我的查询集吗?或者对我来说构建我的查询集是否有更好/更有效的方法?

编辑:

我尝试了下面建议的 Andrey 的解决方案(及其变体),但这也不起作用:

>>> MyClassB.objects.filter(my_class_as__pk__in=[c.pk, d.pk])
[<MyClassB: <MyClassB ID: 1; name: U>>, <MyClassB: <MyClassB ID: 1; name: U>>]

>>> MyClassB.objects.filter(my_class_as__in=[c, d])
[<MyClassB: <MyClassB ID: 1; name: U>>, <MyClassB: <MyClassB ID: 1; name: U>>]

【问题讨论】:

    标签: python django orm many-to-many django-queryset


    【解决方案1】:

    你试过了吗:

    MyClassB.objects.filter(my_class_as__pk__in=[c.pk, d.pk])?
    

    【讨论】:

    • 是的,请参阅我的原始问题的编辑。它没有给出不同的结果。
    • 哦,最后加上distinct()就行了。这将为您提供独特的对象。
    猜你喜欢
    • 2020-12-19
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2020-08-28
    • 2011-08-10
    相关资源
    最近更新 更多