Lorsque vous développez avec Django, vous êtes souvent confronté au terme 'Lazy Evaluation'.
Cependant, beaucoup se demandent ce que ce concept signifie exactement et comment il fonctionne dans Django.
Dans cet article, nous allons examiner ce qu'est la "Lazy Evaluation" et comment elle est utilisée dans le ORM de Django.

1️⃣ Qu'est-ce que la Lazy Evaluation ?

"Ne pas récupérer les données de la base de données tant que cela n'est pas nécessaire !"

Le QuerySet de Django suit par défaut la Lazy Evaluation.
C'est-à-dire que même si vous créez un QuerySet, la requête ne s'exécute pas tant que les données ne sont pas réellement demandées.

Exemple : Lazy Evaluation

from myapp.models import Post

# Création d'un QuerySet (les données ne sont pas encore récupérées de la DB)
post_list = Post.objects.filter(status='PB')  

print(post_list)  
# <QuerySet [ ]># ✅ La requête n'a pas encore été exécutée dans la DB

# 🔥 La requête DB s'exécute réellement lorsque vous consultez les données
for post in post_list:
    print(post.title)  # 🚀 ici, la requête DB se produit
  • post_list est un objet QuerySet, mais il n'accède pas encore à la DB
  • Mais lorsque les données sont utilisées, la requête s'exécute réellement

C'est ça, la "Lazy Evaluation" ! 

2️⃣ Qu'est-ce que l'Eager Evaluation ?

"Récupérer les données immédiatement et les transformer en liste ou en variable !"

Pour déclencher immédiatement le QuerySet, vous pouvez utiliser l'Eager Evaluation.

Exemple : Eager Evaluation

post_list = list(Post.objects.filter(status='PB'))  # ✅ Exécution immédiate de la requête DB

print(post_list)  
# [<Post: Post 1>, <Post: Post 2>] # 🚀 Liste d'objets réelle retournée, pas un QuerySet!

📌 Lorsque l'Eager Evaluation est appliquée :

  • Le QuerySet est transformé en liste, accédant immédiatement aux données
  • Plus aucune fonctionnalité de Django ORM (.filter(), .annotate()) ne peut être utilisée

3️⃣ Évaluations immédiates avec `.values()` et `.values_list()`

.values() et .values_list() maintiennent également par défaut la Lazy Evaluation, mais
si vous les enveloppez avec list(), cela appliquera l'Eager Evaluation.

✅ Maintien de la Lazy Evaluation

post_list = Post.objects.filter(status='PB').values("id", "title")

print(post_list)  
# <QuerySet [{'id': 1, 'title': 'First Post'}, {'id': 2, 'title': 'Second Post'}]>  # Objet QuerySet

🚨 Dans cet état, le QuerySet existe toujours, donc il est évalué chaque fois que les données sont utilisées. 🔥 Application de l'Eager Evaluation

post_list = list(Post.objects.filter(status='PB').values("id", "title"))

print(post_list)  
# [{'id': 1, 'title': 'First Post'}, {'id': 2, 'title': 'Second Post'}]  # 🚀 Évalué immédiatement (transformé en liste)

✅ Maintenant, c'est devenu une liste et non un QuerySet, et vous ne pouvez plus utiliser les fonctionnalités du Django ORM (.filter(), .annotate()). ✅ Mais les données ont été récupérées à l'avance, permettant une utilisation rapide sans accès à la DB par la suite.

4️⃣ `.count()` et `.exists()` dans le QuerySet effectuent une évaluation immédiate !

Le QuerySet Django suit par défaut une évaluation paresseuse, mais certaines méthodes exécutent automatiquement une évaluation immédiate.

.count() (exécution immédiate de la requête)

post_count = Post.objects.filter(status='PB').count()
# ✅ Exécution immédiate de la requête (SELECT COUNT(*) FROM post WHERE status='PB';)

.exists() (exécution immédiate de la requête)

has_published_posts = Post.objects.filter(status='PB').exists()
# ✅ Exécution immédiate de la requête (SELECT 1 FROM post WHERE status='PB' LIMIT 1;)

.count() et .exists() s'exécutent immédiatement sans transformer le QuerySet.

5️⃣ Comparaison entre Lazy Evaluation et Eager Evaluation

  Lazy Evaluation Eager Evaluation
Description Ne pas exécuter la requête tant que cela n'est pas nécessaire Exécuter la requête immédiatement et récupérer des données
Exemple Maintien de l'état QuerySet list(QuerySet), .values_list(), .count()
Avantages Préventif contre les requêtes inutiles vers DB, économie de mémoire Possibilité d'utiliser les données rapidement après la requête DB
Inconvénients Possibilité d'exécuter des requêtes à chaque fois que c'est nécessaire La charge sur la DB se produit immédiatement, opération ORM supplémentaire impossible
Exemples d'utilisation .filter(), .annotate(), .order_by() list(), .count(), .exists(), .values()

 L'application de l'Eager Evaluation (list(QuerySet)) charge les données immédiatement et peut prévenir des requêtes DB supplémentaires !

 Cependant, les fonctionnalités du QuerySet ne peuvent plus être utilisées, donc il faut prendre des décisions prudentes quant à leur application ! 

 

📌 Conclusion

✅ Le QuerySet de Django suit par défaut la Lazy Evaluation.
✅ En utilisant l'Eager Evaluation, vous récupérez les données de la DB immédiatement et le QuerySet est transformé en liste.
✅ En enveloppant .values(), .values_list() avec list(), cela devient une évaluation immédiate.
Maintenir la Lazy Evaluation peut prévenir des requêtes DB inutiles, mais parfois l'Eager Evaluation peut être plus appropriée ! 

 

Django QuerySet Lazy vs Eager Evaluation