При использовании Django ORM есть методы .values()
и .only()
, которые позволяют получать только определенные поля для оптимизации производительности.
Я подробно разбирал метод .values()
в Django QuerySet в предыдущей записи, и, если вы еще не успели ознакомиться, рекомендую вам это сделать. 😊
Чтобы посмотреть предыдущую запись, нажмите!
Что такое метод .values()
в Django QuerySet?
Так как я пишу о .values()
, будет полезно также объяснить метод .only()
, который работает похожим, но все же отличным образом, чтобы глубже понять Django ORM, и я подготовил этот пост. 🚀
1️⃣ Различия между .only()
и .values()
.only() |
.values() |
|
---|---|---|
Форма возврата | Модельный экземпляр (объект модели) | Список словарей (dict list) |
Цель использования | Сохранение объектной модели + загрузка только некоторых полей | Получение только определенных полей и возврат их в виде списка словарей |
Сохранение функциональности ORM | ✅ Сохранена (.save() , .delete() доступны) |
❗ Методы модели недоступны (.save() , .delete() ❌) |
Дополнительная ленивые загрузки | ❗ При доступе к заранее не загруженным полям происходит дополнительный запрос | ✅ Дополнительных запросов нет |
2️⃣ Способ использования и особенности .only()
.only()
- это способ сохранить объект модели, заранее загружая только определенные поля. Однако, если вы получите доступ к полям, не указанным заранее, произойдет ленивая загрузка, что может привести к выполнению дополнительных запросов.
from myapp.models import Post
# QuerySet, загружающий только поля title и author
qs = Post.objects.only("title", "author")
# Проверьте вывод (сам QuerySet готовится к выполнению с задержкой)
print(qs) # SQL не выполняется
# Доступ к полям
for post in qs: # ✅ здесь выполняется SQL
print(post.title) # ✅ заранее загруженное поле (дополнительных запросов нет)
print(post.body) # 🚨 заранее не загруженное поле → дополнительный запрос
🔹 Примечание:
.only()
незамедлительно загружает только указанные поля, остальные поля будут загружены с помощью дополнительных запросов по мере необходимости.
Чтобы избежать ненужных запросов, лучше указывать все необходимые поля в .only()
.
3️⃣ Способ использования и особенности .values()
.values()
возвращает только определенные поля в виде списка словарей. Поскольку он возвращает не объект модели, использование функциональности ORM невозможно.
Тем не менее, сам QuerySet сохраняется, поэтому методы такие как .filter()
, .annotate()
по-прежнему доступны.
# Получите только title и author, возвращая результат в виде словаря
qs = Post.objects.values("title", "author")
# Сам QuerySet подготавливается к выполнению с задержкой (SQL не выполняется)
print(qs)
# Используйте данные словаря (здесь выполняется SQL)
for post in qs:
print(post["title"]) # ✅ дополнительных запросов нет
🔹 Примечание:
При использовании .values()
, поля ForeignKey возвращают по умолчанию только значение ID.
Если вам нужно значение конкретного поля связанной модели, вы должны явно указать его, например, как "author__name"
.
# Получите конкретное значение поля ForeignKey
qs = Post.objects.values("title", "author__name")
for post in qs:
print(post["author__name"]) # ✅ получаем поле name объекта author
В приведенном выше примере мы указали поле "author__name"
, поэтому в результате будет выведено ожидаемое значение author.name, но если бы мы указали "author"
, то просто была бы выведена ID объекта author.
4️⃣ Когда использовать .only()
и .values()
?
Цель использования | Рекомендуется .only() |
Рекомендуется .values() |
---|---|---|
Когда нужно сохранить объект модели | ✅ | ❌ |
Необходимость использовать функциональность ORM (.save() , .delete() , .update() ) |
✅ | ❌ |
Оптимизация производительности (предотвращение загрузки ненужных полей) | ✅ | ✅ |
Предотвращение дополнительных ленивых загрузок | ❌ (возможны дополнительные запросы) | ✅ (дополнительных запросов нет) |
5️⃣ .values()
также имеет ленивую оценку!
.values()
может казаться немедленно оцениваемым, но на самом деле QuerySet в Django по умолчанию все имеет ленивую оценку.
То есть, SQL не выполняется, когда вы вызываете .values()
, а оценивается, когда вы пытаетесь использовать реальные данные. 🚀
✅ .values()
тоже имеет ленивую оценку (SQL не выполняется немедленно)
qs = Post.objects.values("title", "author") # ❌ SQL не выполняется
print(qs) # ❌ выводится только информация об объекте QuerySet (SQL не выполняется)
for post in qs: # ✅ на этом этапе выполняется SQL
print(post["title"])
✅ Когда происходит оценка QuerySet?
QuerySet, включая .values()
, выполняется немедленно (SQL оценивается) в следующих случаях:
- Когда происходят итерации в
for
цикле - Когда вызывается
list(qs)
- Когда вызывается
bool(qs)
(в условиях, таких какif qs:
) - Когда вызываются такие методы, как
.count()
,.exists()
,.first()
,.last()
📌 Заключение
✅ .only()
→ сохранение объектной модели + предварительная загрузка определенных полей
🔹 доступные функциональности ORM (.save()
, .delete()
)
🔹 однако при доступе к заранее не загруженным полям могут возникать дополнительные запросы
✅ .values()
→ возвращает список словарей + отсутствуют дополнительные запросы
🔹 не может использоваться .save()
, .delete()
из-за отсутствия объектной модели
🔹 сам QuerySet сохраняется, так что можно использовать .filter()
, .annotate()
🔹 поля ForeignKey по умолчанию возвращают только значение ID → необходимо указывать как author__name
💡 Таким образом, если нужно сохранить объект модели, используйте .only()
, а для простого извлечения данных выбирайте .values()
! 🚀
🎯 Оптимизация производительности при использовании Django ORM имеет большое значение.
Когда вы сомневаетесь, какую функцию использовать, обратитесь к этому посту, чтобы выбрать оптимальный способ для вашего приложения.
Желаю, чтобы ваши проекты работали более эффективно и быстро! 🔥
댓글이 없습니다.