← Назад к вопросам

Как получать данные из БД с помощью 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 для сложных случаев
Как получать данные из БД с помощью Django ORM? | PrepBro