在使用Django进行开发时,您会经常遇到'延迟评估(Lazy Evaluation)'这一术语。
但是很多人会好奇这个概念究竟是什么,以及它在Django中是如何运作的。
在这篇文章中,我们将探讨'延迟评估'是什么,以及如何在Django ORM中加以利用

1️⃣ 延迟评估(Lazy Evaluation)是什么?

"在需要之前不会从数据库中获取数据!"

Django的QuerySet默认遵循延迟评估(Lazy Evaluation)
也就是说,即使创建了QuerySet,在实际请求数据之前,查询并不会执行。

示例: 延迟评估

from myapp.models import Post

# 创建QuerySet(尚未从数据库获取数据)
post_list = Post.objects.filter(status='PB')  

print(post_list)  
# <QuerySet [ ]># ✅ 尚未对数据库执行查询

# 🔥 在实际查看数据时,数据库查询将被执行
for post in post_list:
    print(post.title)  # 🚀 这里将产生数据库查询
  • post_list是QuerySet对象,但尚未访问数据库
  • 然而,当使用数据时 查询实际上会执行

这就是"延迟评估" (Lazy Evaluation)! 

2️⃣ 立即评估(Eager Evaluation)是什么?

"即时获取数据并转换为列表或变量!"

要打破延迟评估并立即执行QuerySet,可以使用立即评估(Eager Evaluation)

示例: 立即评估

post_list = list(Post.objects.filter(status='PB'))  # ✅ 立即执行数据库查询

print(post_list)  
# [<Post: Post 1>, <Post: Post 2>] # 🚀 返回的是实际对象列表,而不是QuerySet!

📌 应用立即评估后:

  • QuerySet被转换为列表,并立即获取数据
  • 无法再使用Django ORM功能(.filter(), .annotate()

3️⃣ `.values()`和`.values_list()`的立即评估

.values().values_list()通常保持延迟评估,但是,
如果将其用list()包裹,将会应用立即评估

✅ 保持延迟评估

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对象

🚨 在此状态下仍然是QuerySet,因此每次使用数据时都会被评估。 🔥 立即评估已生效

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

print(post_list)  
# [{'id': 1, 'title': 'First Post'}, {'id': 2, 'title': 'Second Post'}]  # 🚀 已立即评估(转换为列表)

✅ 现在已变为列表,无法再使用Django ORM功能(.filter(), .annotate())。 ✅ 但由于提前获取了数据,之后可以快速利用,而无需访问数据库

4️⃣ QuerySet中的.count().exists()会立即评估!

Django QuerySet通常是延迟评估,但某些方法会自动执行立即评估。

.count()(立即查询执行)

post_count = Post.objects.filter(status='PB').count()
# ✅ 立即查询执行(SELECT COUNT(*) FROM post WHERE status='PB';)

.exists()(立即查询执行)

has_published_posts = Post.objects.filter(status='PB').exists()
# ✅ 立即查询执行(SELECT 1 FROM post WHERE status='PB' LIMIT 1;)

.count().exists()会在不转换QuerySet的情况下立即执行。

5️⃣ 延迟评估与立即评估对比总结

  延迟评估 (Lazy Evaluation) 立即评估 (Eager Evaluation)
描述 在需要时不执行查询 立即执行查询并获取数据
示例 保持QuerySet状态 list(QuerySet), .values_list(), .count()
优点 避免不必要的数据库查询,节约内存 在数据库查询后快速利用数据
缺点 可能会在每次需要时执行查询 数据库负载立即产生,无法进行其他ORM操作
使用示例 .filter(), .annotate(), .order_by() list(), .count(), .exists(), .values()

 应用立即评估 (list(QuerySet)) 将数据立即加载并避免额外的数据库查询!

 但是要注意,无法再使用QuerySet功能,因此需要谨慎决定何时应用! 

 

📌 结论

✅ Django的QuerySet默认遵循延迟评估 (Lazy Evaluation)
✅ 使用立即评估(Eager Evaluation)可以立即从数据库获取数据并将QuerySet转换为列表
✅ 将.values().values_list()list()包裹将实现立即评估。
保持延迟评估可以避免不必要的数据库查询,但有时立即评估可能更适合! 

 

Django QuerySet Lazy vs Eager Evaluation