it-swarm-pt.tech

como subconsulta no queryset no django?

como posso ter uma subconsulta no queryset do Django? por exemplo, se eu tiver:

select name, age from person, employee where person.id = employee.id and
employee.id in (select id from employee where employee.company = 'Private')

isto é o que eu fiz ainda.

Person.objects.value('name', 'age')
Employee.objects.filter(company='Private')

mas não está funcionando porque retorna duas saídas ...

30
gadss
ids = Employee.objects.filter(company='Private').values_list('id', flat=True)
Person.objects.filter(id__in=ids).values('name', 'age')
19
Jan Pöschko

conforme mencionado pelo ypercube, seu caso de uso não requer subconsulta.

mas de qualquer maneira, já que muitas pessoas acessam esta página para aprender como fazer uma consulta secundária aqui é como isso é feito.

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

Fonte: http://mattrobenolt.com/the-Django-orm-and-subqueries/

41
Ramast

Você pode criar subconsultas em Django usando um queryset não avaliado para filtrar o seu principal queryyset. No seu caso, seria algo parecido com isto:

employee_query = Employee.objects.filter(company='Private')
people = Person.objects.filter(employee__in=employee_query)

Suponho que você tenha um relacionamento inverso de Person para Employee chamado employee. Achei útil examinar a consulta SQL gerada por um conjunto de consultas quando estava tentando entender como os filtros funcionam.

print people.query

Como outros já disseram, você realmente não precisa de uma subconsulta para o seu exemplo. Você pode simplesmente ingressar na tabela de funcionários:

people2 = Person.objects.filter(employee__company='Private')
9
Don Kirkby

A resposta correta da sua pergunta está aqui https://docs.djangoproject.com/en/2.1/ref/models/expressions/#subquery-expressions

Como um exemplo:

>>> 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]))
3
Dmitry Anch