39 votes

Comment faire une sous-requête dans un queryset en django ?

Comment puis-je avoir une sous-requête dans le queryset de django ? par exemple si j'ai :

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

C'est ce que j'ai fait jusqu'à présent.

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

mais il ne fonctionne pas car il renvoie deux résultats...

52voto

Ramast Points 96

Comme l'a indiqué Ypercube, votre cas d'utilisation ne nécessite pas de sous-requête.

Mais de toute façon, puisque de nombreuses personnes consultent cette page pour apprendre à faire des sous-requêtes, voici comment procéder.

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

Source : http://mattrobenolt.com/the-django-orm-and-subqueries/

33voto

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

12voto

Don Kirkby Points 12671

Vous pouvez créer des sous-requêtes dans Django en utilisant un élément queryset non évalué pour filtrer votre jeu de questions principal. Dans votre cas, cela ressemblerait à quelque chose comme ceci :

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

Je suppose que vous avez une relation inversée de Person a Employee nommée employee . J'ai trouvé utile d'examiner la requête SQL générée par un queryset lorsque j'essayais de comprendre le fonctionnement des filtres.

print people.query

Comme d'autres l'ont dit, vous n'avez pas vraiment besoin d'une sous-requête pour votre exemple. Vous pouvez simplement joindre la table des employés :

people2 = Person.objects.filter(employee__company='Private')

10voto

Dmitry Anch Points 194

La bonne réponse à votre question se trouve ici https://docs.djangoproject.com/en/2.1/ref/models/expressions/#subquery-expressions

A titre d'exemple :

>>> 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]))

0voto

vikas thakur Points 49
hero_qs = Hero.objects.filter(category=OuterRef("pk")).order_by("-benevolence_factor")
Category.objects.all().annotate(most_benevolent_hero=Subquery(hero_qs.values('name')[:1]))

le sql généré

SELECT "entities_category"."id",
       "entities_category"."name",
  (SELECT U0."name"
   FROM "entities_hero" U0
   WHERE U0."category_id" = ("entities_category"."id")
   ORDER BY U0."benevolence_factor" DESC
   LIMIT 1) AS "most_benevolent_hero"
FROM "entities_category"

Pour plus de détails, voir cet article .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X