Ответ
Django ORM предоставляет мощные инструменты для построения сложных и оптимизированных запросов к базе данных напрямую из Python-кода. Это повышает читаемость, безопасность и переносимость кода между разными СУБД.
Основные инструменты:
-
F()выражения: Позволяют ссылаться на значение поля модели непосредственно в запросе. Это дает возможность выполнять операции на уровне базы данных, избегая извлечения данных в Python.- Пример: Найти товары, у которых количество на складе меньше, чем заказанное количество.
from django.db.models import F
Product.objects.filter(stock_count__lt=F('ordered_count'))
- Пример: Найти товары, у которых количество на складе меньше, чем заказанное количество.
-
Q()объекты: Используются для построения сложных логических условий с использованием операторовИ(&),ИЛИ(|) иНЕ(~).- Пример: Найти пользователей, которые либо активны, либо заходили в последний месяц.
from django.db.models import Q from django.utils import timezone from datetime import timedelta
one_month_ago = timezone.now() - timedelta(days=30) User.objects.filter(Q(is_active=True) | Q(last_login__gte=one_month_ago))
- Пример: Найти пользователей, которые либо активны, либо заходили в последний месяц.
-
Subquery: Позволяет встраивать одинQuerySetв другой в качестве подзапроса. Часто используется для аннотаций.- Пример: Для каждого поста аннотировать текст последнего комментария.
from django.db.models import OuterRef, Subquery
latest_comment = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at') Post.objects.annotate( last_comment_text=Subquery(latest_comment.values('text')[:1]) )
- Пример: Для каждого поста аннотировать текст последнего комментария.
-
Exists: Более эффективный способ проверить существование связанных записей, чемcount() > 0, так как он используетEXISTSна уровне SQL.- Пример: Найти все посты, у которых есть хотя бы один комментарий.
from django.db.models import Exists, OuterRef
comments = Comment.objects.filter(post=OuterRef('pk')) Post.objects.annotate(has_comments=Exists(comments)).filter(has_comments=True)
- Пример: Найти все посты, у которых есть хотя бы один комментарий.