【问题标题】:Django filter by many to many with exact same queryDjango 使用完全相同的查询进行多对多过滤
【发布时间】:2019-05-23 11:48:29
【问题描述】:

在 django 中有什么方法可以通过查询集或 ids 列表过滤具有多对多关系的对象。在多对多中获取具有完全相同值的查询。 型号

class Parent(models.Model):
    name = models.CharField(max_length=1000)
    children = models.ManyToManyField(Child, blank=True)

观看次数

def filter_parents(request):
    children = Child.objects.filter(id__in=[1,2,3])
    parents = Parent.objects.filter(child=child)
    return parents

预计: 我正在寻找在多对多领域具有完全相同孩子的过滤父母

【问题讨论】:

  • 请确认,您想获取Parents 的查询集,在child 字段中具有相同的孩子? Like [Parent(name='1', child='10'), Parent(name='2', child='10'), Parent(name='3', child='20'), Parent(name='4', child='20'), ] Like a queryset of Parents whoes children has at list 2 Parents,是吗?
  • @SergeyPugach 是的,有些孩子有 2 个父母,有些父母有几个孩子(比如 2 个或更多)。我有一组儿童查询(按姓名或 ID 或年龄过滤)。并且需要让父母拥有完全相同的多对多记录。
  • @SergeyPugach 我的意思是不要通过 _set 获取父母,而是通过多对多字段过滤它们
  • 所以你需要有至少 2 个孩子的父母和那些孩子在你的查询集中的人 children 对吗?
  • @SergeyPugach 对,但稍作修正,可能会有 1 或 4 个孩子,数量是动态的。 Child.objects.filter(id__in=request.GET.get('ids_list', ''))

标签: django many-to-many


【解决方案1】:

您可以针对这种情况使用链式过滤。

from django.db.models import Count

children_id_list = [1, 2, 3]
parents = Parent.objects.annotate(count=Count('children')).filter(count=len(children_id_list))

for child_id in children_id_list:
    parents = parents.filter(children__id=child_id)

或者您可以使用 lambda 过滤:

c_id_list = [1, 2, 3]
parents = Parent.objects.annotate(count=Count('children')).filter(count=len(children_id_list))
parents = reduce(lambda p, id: parents.filter(child=id), c_id_list, parents)

或者你可以使用Q()查询:

from django.db.models import Count, Q

children_id_list = [1, 2, 3]
parents = Parent.objects.annotate(count=Count('children')).filter(count=len(children_id_list))

query = Q()
for child_id in children_id_list:
    query &= Q(children__id=child_id)
parents = parents.filter(query)

因此,您将只获得在您的 id 列表中包含所有 childrenParent 对象。

【讨论】:

  • 是的......这个解决方案看起来很困难,但我也找不到更优雅的解决方案。谢谢!
【解决方案2】:

我想这就是你要找的东西:

parents = Parent.objects.filter(children__id__in=[1,2,3])

更新:

我认为您需要 unpack 子 ID,然后执行以下操作。

parents = Parent.objects.annotate(child_id=F('children__id'))
                        .filter(child__id__in=[1,2,3])
                        .order_by('email').distinct('email')

请注意order_by 在这里是必需的,因为没有它会破坏distinct 操作。请注意,您应该将 email 替换为您的 User 模型中唯一的字段。

这应该完全符合您的要求。

【讨论】:

  • 不。看,即使有 children__id = [1,2,3,4,5,9],这段代码也会显示父母我需要有完全相同孩子的父母,没有更多
  • 哦。那么你想要匹配所有 3 个孩子吗?
  • 你没有孩子的身份证,你想得到一对有相同孩子的父母?
  • 我有孩子的身份证,Child.objects.filter(id__in=request.GET.get('ids_list', ''))。并且需要有孩子的父母。顺便说一句,如果孩子被收养,甚至可能有两个以上的父母
猜你喜欢
  • 2020-06-16
  • 2020-04-16
  • 2015-02-17
  • 1970-01-01
  • 2021-09-01
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 2015-01-11
相关资源
最近更新 更多