如何在django的queryset中查询子查询?

gad*_*dss 28 python django

我怎么能在django的查询集中有一个子查询?例如,如果我有:

select name, age from person, employee where person.id = employee.id and
employee.id in (select id from employee where employee.company = 'Private')
Run Code Online (Sandbox Code Playgroud)

这就是我所做的.

Person.objects.value('name', 'age')
Employee.objects.filter(company='Private')
Run Code Online (Sandbox Code Playgroud)

但它没有工作,因为它返回两个输出...

Ram*_*ast 42

正如ypercube所提到的,您的用例不需要子查询.

但无论如何,因为很多人进入这个页面学习如何做分查询这里是如何做到的.

employee_query = Employee.objects.filter(company='Private').only('id').all()
Person.objects.value('name', 'age').filter(id__in=employee_query)
Run Code Online (Sandbox Code Playgroud)

资料来源:http: //mattrobenolt.com/the-django-orm-and-subqueries/

  • 在 django 3.2 中 .only('id') 是 .values_list('id', flat=True) (3认同)

Jan*_*hko 21

ids = Employee.objects.filter(company='Private').values_list('id', flat=True)
Person.objects.filter(id__in=ids).values('name', 'age')
Run Code Online (Sandbox Code Playgroud)

  • 这不是子查询,`values_list`不返回查询集.这会产生两个单独的查询. (28认同)
  • `values_list`返回一个`ValuesQuerySet`,这两行实际上将转换为带有子查询的单个查询. (15认同)
  • 事实上,我不知道是什么让我这么想并这么说......也许当时 ValuesListQuerySet 的 repr 看起来像一个列表和/或它在 2016 年没有转换为子查询,但我没有证据可以辩护我。 (6认同)
  • 这实际上会生成 **only 一个** 查询,这意味着答案是正确的。此外, 1. `.values('id')` 也同样有效, 2. 推荐使用 `pk` 字段。 (3认同)
  • 不是子查询,只是两个查询. (2认同)
  • @Antoine实际上,**这是一个子查询**,并且`.values_list()` **返回一个查询集!**如果你不相信我,请尝试[记录sql](https://stackoverflow.com /questions/4375784/log-all-sql-queries)这个答案。 (2认同)
  • 我觉得有义务对此投赞成票,因为 12 个人显然不知道查询集是如何工作的。 (2认同)

Dmi*_*nch 11

您的问题的正确答案在这里https://docs.djangoproject.com/en/2.1/ref/models/expressions/#subquery-expressions

举个例子:

>>> from django.db.models import OuterRef, Subquery
>>> newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
>>> Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))
Run Code Online (Sandbox Code Playgroud)


Don*_*kby 9

您可以使用未评估的查询集来过滤主查询集,从而在Django中创建子查询.在你的情况下,它看起来像这样:

employee_query = Employee.objects.filter(company='Private')
people = Person.objects.filter(employee__in=employee_query)
Run Code Online (Sandbox Code Playgroud)

我假设你有一个从一个相反的关系PersonEmployee命名employee.我发现当我试图了解过滤器的工作原理时,查看查询集生成的SQL查询会很有帮助.

print people.query
Run Code Online (Sandbox Code Playgroud)

正如其他人所说的那样,你的实例并不需要子查询.您可以加入员工表:

people2 = Person.objects.filter(employee__company='Private')
Run Code Online (Sandbox Code Playgroud)