2020-12-04 11:13:06 +01:00
|
|
|
### 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`.
|
|
|
|
|
2020-12-04 11:28:53 +01:00
|
|
|
Nous pourrions penser qu'utiliser un itérateur permettrait de combiner les deux, mais ce n'est pas le cas...
|
2020-12-04 11:13:06 +01:00
|
|
|
|
2020-12-04 11:28:53 +01:00
|
|
|
Comme l'indique 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 qu'il y a d'éléments, ce que nous cherchons à éviter.
|
2020-12-04 11:13:06 +01:00
|
|
|
|
|
|
|
[source,python]
|
|
|
|
----
|
|
|
|
informations = (
|
|
|
|
<MyObject>.objects.filter(<my_criteria>)
|
|
|
|
.select_related(<related_field>)
|
|
|
|
.prefetch_related(<related_field>)
|
|
|
|
.iterator(chunk_size=1000)
|
|
|
|
)
|
|
|
|
----
|