DJANGO:从子查询集中获取父查询集

Posted

技术标签:

【中文标题】DJANGO:从子查询集中获取父查询集【英文标题】:DJANGO: Get a parent queryset from a child queryset 【发布时间】:2021-12-10 19:44:27 【问题描述】:

假设我的models.py 有以下内容:

from django.db import models

class Department(models.model):
    name = models.CharField(max_length=255)

class User(models.model):
    name = models.CharField(max_length=255)
    department = models.ForeignKey(
        Department, related_name="department_users", on_delete=models.CASCADE
    )
    ...

因此,我对我的用户查询集进行了很多复杂的过滤,以获取被认为是“活跃”的用户子集,但现在我需要生成至少有一个“活跃”用户的部门列表。

我知道我可以使用反向查找,例如:Department.objects.filter(department_users__name__contains=...) 等并重新进行过滤,但我想知道是否有办法直接从“活动”用户查询集中获取该信息。

我尝试使用.values(),但这给了我一个字典查询集,我真的想要一个 django 模型查询集,这样我就可以对部门查询集进行进一步过滤。

你们知道有没有办法做到这一点?

【问题讨论】:

【参考方案1】:

如果您有一个Users 的查询集,您可以加载users 并查询部门:

Department.objects.filter(<strong>department_users__in=list(</strong><i>queryset_of_users</i><strong>)</strong>).distinct()

您也可以在不具体化用户列表的情况下执行此操作:

Department.objects.filter(<strong>department_users__in=<i>queryset_of_users</i></strong>).distinct()

这里您的queryset_of_users 将是一个子查询,但这意味着数据库将执行第二次确定活动用户的工作。

.distinct() 子句将阻止返回Department 的次数与该部门的queryset_of_users 中的Users 一样多。

【讨论】:

我认为这种方式可能比仅仅使用反向查找路径效率低,因为您正在交叉引用两个对象列表,似乎没有办法避免对部门进行所有过滤. @LuizF.Bianchi:通过调用list(...) 强制queryset_of_users 进行评估,它会缓存用户。如果您稍后在程序中迭代queryset_of_users,它将不会进行第二次查询。这个想法是查询集只会评估一次。当然,如果您构建一个新的查询集(例如通过在 queryset_of_users 上调用 .filter(...),它会再次创建一个必须评估的新查询集。 @LuizF.Bianchi:换句话说,通过强制评估第一个list(queryset_of_users),您将阻止在枚举queryset_of_users 时对其进行第二次评估。 我同意你在这方面的看法,但进行“__in”查找也很费力。 @LuizF.Bianchi:它将传递一个主键列表,因此查询将是WHERE user.id IN (1,4,7, 15)。您可以使用.distinct() 来防止多次调用同一部门的查询。

以上是关于DJANGO:从子查询集中获取父查询集的主要内容,如果未能解决你的问题,请参考以下文章

如何从子表单中获取父 Symfony3 表单的值?

如何在 django 查询集中获取表的计算元素?

从 django 的查询集中获取第一个对象的最快方法?

在 django 的查询集中获取对象的计数

Django - 如何从模板中的查询集中获取最后一项

Django通过查询集中的唯一值获取总计数和计数