gwift-book/source/part-3-django-concepts/queryset.adoc

1.5 KiB
Raw Blame History

Querysets & managers

Jointures

Pour appliquer une jointure sur un modèle, nous pouvons passer par les méthodes select_related et prefetch_related. Il faut cependant faire très attention au prefetch related, qui fonctionne en fait comme une grosse requête dans laquelle nous trouvons un IN (…​). Càd que Django va récupérer tous les objets demandés initialement par le queryset, pour ensuite prendre toutes les clés primaires, pour finalement faire une deuxième requête et récupérer les relations externes.

Au final, si votre premier queryset est relativement grand (nous parlons de 1000 à 2000 éléments, en fonction du moteur de base de données), la seconde requête va planter et vous obtiendrez une exception de type django.db.utils.OperationalError: too many SQL variables.

Nous pourrions penser quutiliser un itérateur permettrait de combiner les deux, mais ce nest pas le cas…

Comme lindique la documentation:

Note that if you use iterator() to run the query, prefetch_related() calls will be ignored since these two optimizations do not make sense together.

Ajouter un itérateur va en fait forcer le code à parcourir chaque élément de la liste, pour lévaluer. Il y aura donc (à nouveau) autant de requêtes quil y a déléments, ce que nous cherchons à éviter.

informations = (
  <MyObject>.objects.filter(<my_criteria>)
  .select_related(<related_field>)
  .prefetch_related(<related_field>)
  .iterator(chunk_size=1000)
)