【问题标题】:DJANGO: Get a parent queryset from a child querysetDJANGO:从子查询集中获取父查询集
【发布时间】: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 模型查询集,这样我就可以对部门查询集进行进一步过滤。

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

【问题讨论】:

    标签: django django-models django-rest-framework django-filter


    【解决方案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() 来防止多次调用同一部门的查询。
    猜你喜欢
    • 2012-03-02
    • 2018-12-04
    • 2015-03-20
    • 1970-01-01
    • 1970-01-01
    • 2019-07-01
    • 2018-11-18
    • 2019-08-11
    • 1970-01-01
    相关资源
    最近更新 更多