Al desarrollar con Django, a menudo te encuentras con el término 'Evaluación Diferida (Lazy Evaluation)'.
Sin embargo, muchos se preguntan qué significa exactamente este concepto y cómo funciona en Django.
En este artículo, vamos a explorar qué es la 'Evaluación Diferida' y cómo se utiliza en Django ORM.

1️⃣ ¿Qué es la Evaluación Diferida (Lazy Evaluation)?

"¡No traigas datos de la DB hasta que sea necesario!"

El QuerySet de Django sigue, por defecto, la Evaluación Diferida (Lazy Evaluation).
Es decir, aunque se crea un QuerySet, la consulta no se ejecuta hasta que se solicita realmente los datos.

Ejemplo: Evaluación Diferida

from myapp.models import Post

# Crear QuerySet (aún no se traen datos de la DB)
post_list = Post.objects.filter(status='PB')  

print(post_list)  
# <QuerySet [ ]># ✅ Aún no se ejecuta la consulta en la DB

# 🔥 La consulta en la DB se ejecuta al acceder a los datos
for post in post_list:
    print(post.title)  # 🚀 La consulta a la DB ocurre aquí
  • post_list es un objeto QuerySet, pero aún no accede a la DB
  • Sin embargo, cuando se utiliza los datos, la consulta se ejecuta realmente

¡Eso es la "Evaluación Diferida"! 

2️⃣ ¿Qué es la Evaluación Inmediata (Eager Evaluation)?

"¡Obtén los datos de inmediato y conviértelos en una lista o variable!"

Para forzar la ejecución inmediata del QuerySet y romper la evaluación diferida, se puede usar la Evaluación Inmediata (Eager Evaluation).

Ejemplo: Evaluación Inmediata

post_list = list(Post.objects.filter(status='PB'))  # ✅ Se ejecuta la consulta en DB de inmediato

print(post_list)  
# [<Post: Post 1>, <Post: Post 2>] # 🚀 Devuelve una lista de objetos reales, no un QuerySet.

📌 Al aplicar la evaluación inmediata:

  • El QuerySet se convierte en una lista y obtiene los datos de forma inmediata
  • Ya no se pueden utilizar las funciones de Django ORM (.filter(), .annotate())

3️⃣ Evaluación Inmediata de `.values()` y `.values_list()`

.values() y .values_list() también mantienen por defecto la Evaluación Diferida, pero,
si se envuelven en list(), se aplica evaluación inmediata.

✅ Mantiene la Evaluación Diferida (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'}]>  # Objeto QuerySet

🚨 En este estado, sigue siendo un QuerySet, así que se evalúa cada vez que se utilizan los datos. 🔥 Aplicación de evaluación inmediata

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

print(post_list)  
# [{'id': 1, 'title': 'First Post'}, {'id': 2, 'title': 'Second Post'}]  # 🚀 Evaluado de inmediato (convertido a lista)

✅ Ahora se ha convertido en una lista, no un QuerySet, y ya no se pueden utilizar las funciones de Django ORM (.filter(), .annotate()). ✅ Pero se han obtenido los datos de antemano, por lo que se pueden usar de manera rápida sin acceso a la DB.

4️⃣ ¡`.count()` y `.exists()` se evalúan de inmediato en el QuerySet!

El QuerySet de Django sigue, por defecto, la evaluación diferida, pero algunos métodos ejecutan automáticamente la evaluación inmediata.

.count() (ejecuta consulta inmediatamente)

post_count = Post.objects.filter(status='PB').count()
# ✅ Consulta ejecutada de inmediato (SELECT COUNT(*) FROM post WHERE status='PB';)

.exists() (ejecuta consulta inmediatamente)

has_published_posts = Post.objects.filter(status='PB').exists()
# ✅ Consulta ejecutada de inmediato (SELECT 1 FROM post WHERE status='PB' LIMIT 1;)

.count() y .exists() se ejecutan de inmediato sin transformar el QuerySet.

5️⃣ Comparativa entre Evaluación Diferida y Evaluación Inmediata

  Evaluación Diferida (Lazy Evaluation) Evaluación Inmediata (Eager Evaluation)
Descripción No ejecuta la consulta hasta que sea necesario Ejecuta la consulta de inmediato y obtiene los datos
Ejemplo Mantiene el estado QuerySet list(QuerySet), .values_list(), .count()
Ventajas Previene consultas innecesarias a la DB, ahorra memoria Permite un acceso rápido a los datos después de la consulta a la DB
Desventajas Puede que ejecute la consulta cada vez que sea necesario La carga de la DB ocurre de inmediato, no se pueden realizar más operaciones en ORM
Ejemplos de uso .filter(), .annotate(), .order_by() list(), .count(), .exists(), .values()

 Al aplicar la evaluación inmediata (list(QuerySet)), los datos se cargan de inmediato y se previenen consultas adicionales a la DB!

 Sin embargo, ya no se pueden utilizar las funciones del QuerySet, así que debes decidir cuidadosamente cuándo aplicarlo! 

 

📌 Conclusión

✅ El QuerySet de Django sigue, por defecto, la Evaluación Diferida (Lazy Evaluation).
✅ Al usar la Evaluación Inmediata (Eager Evaluation), se obtienen los datos de inmediato desde la DB y el QuerySet se convierte en una lista.
✅ Al envolver .values() y .values_list() en list(), se aplica la evaluación inmediata.
Mantener la Evaluación Diferida puede prevenir consultas innecesarias a la DB, pero a veces la evaluación inmediata puede ser más apropiada. 

 

Django QuerySet Lazy vs Eager Evaluation