При разработке на Django вы часто сталкиваетесь с термином 'ленивая оценка (Lazy Evaluation)'.
Но многие могли не понимать, что именно означает этот концепт и как он работает в Django.
В этой статье мы рассмотрим 'что такое ленивая оценка и как она используется в Django ORM'.
1️⃣ Что такое ленивая оценка (Lazy Evaluation)?
"Данные из базы данных не извлекаются, пока они не понадобятся!"
QuerySet в Django в основном следует ленивой оценке (Lazy Evaluation).
То есть, даже если вы создадите QuerySet, запрос не выполняется до тех пор, пока фактически не будет запрошен набор данных.
✅ Пример: Ленивая оценка
from myapp.models import Post
# Создание QuerySet (данные из DB еще не извлечены)
post_list = Post.objects.filter(status='PB')
print(post_list)
# <QuerySet [ ]># ✅ Запрос к DB еще не выполнен
# 🔥 Запрос к DB выполняется при фактическом извлечении данных
for post in post_list:
print(post.title) # 🚀 Запрос к DB происходит здесь
- post_list — это объект QuerySet, но он еще не обращается к БД
- Тем не менее, при использовании данных запрос фактически выполняется
✅ Это и есть "ленивая оценка"!
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()
, то применяется немедленная оценка.
✅ Сохранение ленивой оценки (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
🚨 В этом состоянии это все еще 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'}] # 🚀 Применена немедленная оценка (преобразовано в список)
✅ Теперь это список, а не QuerySet, и больше нельзя использовать функции Django ORM (.filter()
, .annotate()
). ✅ Но данные были извлечены заранее, что позволяет быстро использовать их без доступа к БД.
4️⃣ `.count()` и `.exists()` в QuerySet выполняются немедленно!
QuerySet в Django в основном ленивый, но некоторые методы автоматически выполняют немедленную оценку.
.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 больше не доступны, поэтому нужно тщательно решать, когда применять это!
📌 Заключение
✅ QuerySet в Django в основном следует ленивой оценке (Lazy Evaluation).
✅ Используя немедленную оценку (Eager Evaluation), данные извлекаются немедленно из БД, и QuerySet преобразуется в список.
✅ Обернув .values()
, .values_list()
в list()
, происходит немедленная оценка.
✅ Сохраняя ленивую оценку, можно предотвратить ненужные запросы к БД, но иногда немедленная оценка может быть более уместной!
Комментариев нет.