When developing with Django, you often encounter the term 'Lazy Evaluation'.
However, many of you might wonder what exactly this concept is and how it works in Django.
In this post, we will explore what 'Lazy Evaluation' means and how it is utilized in Django ORM.

1️⃣ What is Lazy Evaluation?

"Do not fetch data from the DB until necessary!"

Django's QuerySet follows Lazy Evaluation by default.
In other words, even if you create a QuerySet, the query is not executed until you actually request the data.

Example: Lazy Evaluation

from myapp.models import Post

# Create a QuerySet (no data fetched from DB yet)
post_list = Post.objects.filter(status='PB')  

print(post_list)  
# <QuerySet [ ]># ✅ No query executed on DB yet

# 🔥 The DB query is executed when data is actually accessed
for post in post_list:
    print(post.title)  # 🚀 DB query occurs here
  • post_list is a QuerySet object, but it does not access the DB yet
  • However, when data is used, the query is executed

This is what "Lazy Evaluation" is!

2️⃣ What is Eager Evaluation?

"Fetch data immediately and convert it into a list or variable!"

To break the paradigm of Lazy Evaluation and execute the QuerySet immediately, you can use Eager Evaluation.

Example: Eager Evaluation

post_list = list(Post.objects.filter(status='PB'))  # ✅ Executes DB query immediately

print(post_list)  
# [<Post: Post 1>, <Post: Post 2>] # 🚀 Returns an actual object list instead of a QuerySet!

📌 Applying Eager Evaluation:

  • QuerySet is converted into a list and fetches data immediately
  • Can no longer use Django ORM functionality (.filter(), .annotate())

3️⃣ Immediate Evaluation with `.values()` and `.values_list()`

.values() and .values_list() also maintain Lazy Evaluation by default,
but wrapping them in list() applies immediate evaluation.

✅ Maintaining 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'}]>  # QuerySet object

🚨 In this state, it is still a QuerySet, so it is evaluated every time data is used. 🔥 Apply Immediate 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'}]  # 🚀 Evaluated immediately (converted to list)

✅ Now it has become a list instead of a QuerySet, and the Django ORM functionality (.filter(), .annotate()) cannot be used. ✅ But since the data has been fetched in advance, it can be quickly utilized without further DB access.

4️⃣ The `.count()` and `.exists()` methods on QuerySet evaluate immediately!

Django QuerySet is usually lazy evaluated, but certain methods automatically execute immediate evaluations.

.count() (immediate query execution)

post_count = Post.objects.filter(status='PB').count()
# ✅ Executes immediate query (SELECT COUNT(*) FROM post WHERE status='PB';)

.exists() (immediate query execution)

has_published_posts = Post.objects.filter(status='PB').exists()
# ✅ Executes immediate query (SELECT 1 FROM post WHERE status='PB' LIMIT 1;)

.count() and .exists() execute immediately without converting the QuerySet.

5️⃣ Summary Comparison: Lazy Evaluation vs. Eager Evaluation

  Lazy Evaluation Eager Evaluation
Description Does not execute query until necessary Executes query immediately and fetches data
Example Maintains QuerySet state list(QuerySet), .values_list(), .count()
Advantage Prevents unnecessary DB queries, saves memory Quickly utilize data after DB query
Disadvantage Queries might execute every time when needed Immediate load on DB, no additional ORM operations allowed
Usage Examples .filter(), .annotate(), .order_by() list(), .count(), .exists(), .values()

Applying Eager Evaluation (list(QuerySet)) allows data to be loaded immediately and prevents additional DB queries!

However, since the QuerySet functionalities can no longer be used, careful consideration should be given to when to apply it!

📌 Conclusion

✅ Django's QuerySet follows Lazy Evaluation by default.
✅ Using Eager Evaluation, you can immediately fetch data from the DB and convert the QuerySet into a list.
✅ Wrapping .values() and .values_list() with list() applies immediate evaluation.
Maintaining Lazy Evaluation can prevent unnecessary DB queries, but sometimes immediate evaluation might be more appropriate!

Django QuerySet Lazy vs Eager Evaluation