← Назад к вопросам
Как получать данные из БД с помощью Django ORM?
2.3 Middle🔥 241 комментариев
#Django#Базы данных (SQL)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Получение данных из БД с помощью Django ORM
Django Object-Relational Mapping (ORM) предоставляет удобный способ работать с данными БД, используя объекты Python вместо написания SQL запросов напрямую. Это один из главных инструментов для работы с данными в Django.
Базовые операции выборки
1. Получение всех объектов
from myapp.models import User
# Получить все пользователи
all_users = User.objects.all()
# QuerySet — это ленивая выборка, запрос выполняется при итерации
for user in all_users:
print(user.name)
2. Фильтрация данных
# Получить одного пользователя по id
user = User.objects.get(id=1)
# Получить пользователей, фильтруя по полю
active_users = User.objects.filter(is_active=True)
# Несколько условий (И логика)
adult_users = User.objects.filter(is_active=True, age__gte=18)
# Исключение (противоположное filter)
inactive_users = User.objects.exclude(is_active=True)
3. Получение одного объекта
# Получить объект или выбросить исключение
user = User.objects.get(id=1) # DoesNotExist если не найден
# Получить первый объект из QuerySet
first_user = User.objects.filter(is_active=True).first()
# Безопасно получить с дефолтом
user = User.objects.filter(email='test@example.com').first()
if user is None:
print("Пользователь не найден")
Операторы сравнения (Lookups)
# Больше, меньше
users = User.objects.filter(age__gt=18) # age > 18
users = User.objects.filter(age__lt=65) # age < 65
users = User.objects.filter(age__gte=18) # age >= 18
users = User.objects.filter(age__lte=65) # age <= 65
# Равно, не равно
users = User.objects.filter(status="active") # status = 'active'
users = User.objects.exclude(status="active") # status != 'active'
# Входит в список
users = User.objects.filter(status__in=["active", "pending"])
# Содержит строку (LIKE)
users = User.objects.filter(name__icontains="john") # case-insensitive
users = User.objects.filter(email__startswith="john")
users = User.objects.filter(email__endswith="@gmail.com")
# Диапазон
from django.utils import timezone
from datetime import timedelta
last_week = timezone.now() - timedelta(days=7)
recent_users = User.objects.filter(created_at__gte=last_week)
Связанные данные (Joins)
from myapp.models import User, Post
# Получить посты конкретного пользователя (ForeignKey)
posts = Post.objects.filter(user_id=1)
posts = Post.objects.filter(user__id=1)
# Следование по связи и фильтрация
posts = Post.objects.filter(user__email="test@example.com")
# Обратные отношения (post_set)
user = User.objects.get(id=1)
user_posts = user.post_set.all()
# Многие-ко-многим
from myapp.models import Article, Tag
articles = Article.objects.filter(tags__name="python")
Оптимизация запросов
# Select related — загружает связанные объекты одним запросом
# Используй для ForeignKey и OneToOne
posts = Post.objects.select_related('user', 'category').all()
# Prefetch related — отдельные запросы для связей, но оптимизирует
# Используй для ManyToMany и обратные ForeignKey
users = User.objects.prefetch_related('posts').all()
# Комбинирование
posts = Post.objects.select_related('user').prefetch_related('comments').all()
# Only и defer — загружай только нужные поля
users = User.objects.only('id', 'name', 'email')
users = User.objects.defer('bio', 'avatar') # загружай всё кроме этого
Сортировка
# По одному полю
users = User.objects.order_by('name')
users = User.objects.order_by('-created_at') # по убыванию
# По нескольким полям
users = User.objects.order_by('status', '-created_at')
# Удалить сортировку
users = User.objects.order_by().all()
Агрегация и аннотация
from django.db.models import Count, Sum, Avg, Max, Min
# Подсчёт
user_count = User.objects.count()
# Сумма, среднее значение
total_orders = Order.objects.aggregate(Sum('price'))
avg_price = Product.objects.aggregate(Avg('price'))
# Аннотация — добавляет поле в результат
from django.db.models import Count
users = User.objects.annotate(post_count=Count('posts'))
for user in users:
print(f"{user.name}: {user.post_count} постов")
# Фильтрация по аннотированному полю
users = User.objects.annotate(post_count=Count('posts')).filter(post_count__gt=5)
Срезы QuerySet
# Ограничение результатов
first_10 = User.objects.all()[:10]
# Пагинация
page_2 = User.objects.all()[10:20]
# Получить одного пользователя
user = User.objects.all()[0]
Значения (Values)
# Получить словари вместо объектов (быстрее)
users_dicts = User.objects.values('id', 'name', 'email')
# Получить кортежи
user_tuples = User.objects.values_list('id', 'name')
# Плоский список
ids = User.objects.values_list('id', flat=True)
Существование данных
# Проверить наличие объектов
if User.objects.filter(email='test@example.com').exists():
print("Пользователь существует")
# Проверить на пустоту
if not User.objects.filter(age__lt=18).exists():
print("Нет несовершеннолетних")
Необработанные SQL запросы (если ORM недостаточно)
from django.db import connection
# Выполнить сырой SQL
users = User.objects.raw('SELECT * FROM users WHERE age > %s', [18])
# Использовать connection.cursor() для полного контроля
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM users WHERE age > %s", [18])
users = cursor.fetchall()
Итого
Django ORM обеспечивает мощный и безопасный способ работы с БД:
all()иfilter()для базовых запросов- Lookups (
__gt,__lte,__in) для условий select_related()иprefetch_related()для оптимизацииannotate()иaggregate()для вычисленийvalues()для оптимизации памяти- Raw SQL как fallback для сложных случаев