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

В чём разница между фильтром и Deferred?

1.7 Middle🔥 61 комментариев
#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между filter и Deferred в Django ORM

Это фундаментальная разница в том, как Django ORM строит и выполняет SQL запросы. Понимание этого различия критично для написания оптимальных запросов к базе данных.

Filter — условия WHERE для выборки данных

filter() — это метод для фильтрации записей по определённым условиям. Он создаёт SQL WHERE часть запроса.

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    email = models.EmailField()

# filter() создаёт WHERE условие
users = User.objects.filter(age__gte=18)
# SELECT * FROM users WHERE age >= 18;

# Можно объединить несколько filter
users = User.objects.filter(age__gte=18).filter(name__startswith='A')
# SELECT * FROM users WHERE age >= 18 AND name LIKE 'A%';

# exclude() — это инверсия filter
users = User.objects.exclude(age__lt=18)
# SELECT * FROM users WHERE age >= 18;  (эквивалентно)

Deferred — отложенная загрузка полей

Deferred — это техника для оптимизации запросов путём загрузки только нужных полей из БД, а остальные загружаются позже при обращении к ним.

# Без defer — загружает все поля
users = User.objects.all()  # SELECT * FROM users;

# С defer — загружает только нужные поля
users = User.objects.defer('email', 'bio')  # SELECT id, name, age FROM users;

# При обращении к email — новый запрос
for user in users:
    print(user.name)   # В памяти, нет запроса
    print(user.email)  # Запрос к БД! SELECT email FROM users WHERE id = 123;

Ключевые отличия

АспектfilterDeferred
НазначениеФильтрация записей (WHERE)Оптимизация полей (SELECT)
SQL частьWHERE условиеSELECT список полей
Количество записейУменьшает количество строкНе влияет на количество
Количество полейНе влияет (выбирает все)Уменьшает количество колонок
ЛенивостьQuerySet ленивыйОчень ленивый
Типичное использованиеПоиск, сортировка, фильтрацияЭкономия памяти и трафика

Практические примеры filter

Простая фильтрация:

# Точное совпадение
User.objects.filter(name='Alice')
# SELECT * FROM users WHERE name = 'Alice';

# Сравнение
User.objects.filter(age__gt=18)   # age > 18
User.objects.filter(age__gte=18)  # age >= 18
User.objects.filter(age__lt=18)   # age < 18
User.objects.filter(age__lte=18)  # age <= 18

# Содержит подстроку
User.objects.filter(name__icontains='alice')  # case-insensitive

# IN оператор
User.objects.filter(age__in=[18, 19, 20])
# SELECT * FROM users WHERE age IN (18, 19, 20);

# Диапазон дат
from datetime import date
User.objects.filter(created__date__range=['2024-01-01', '2024-12-31'])

# NULL проверка
User.objects.filter(bio__isnull=True)  # Где bio NULL

Сложная фильтрация с Q объектами:

from django.db.models import Q

# OR условие
User.objects.filter(Q(age=18) | Q(age=19))
# SELECT * FROM users WHERE age = 18 OR age = 19;

# AND условие
User.objects.filter(Q(age__gte=18) & Q(name__startswith='A'))

# NOT условие
User.objects.filter(~Q(age__lt=18))
# SELECT * FROM users WHERE NOT (age < 18);

# Сложные условия
User.objects.filter(
    Q(age__gte=18) & (Q(name='Alice') | Q(name='Bob'))
)
# SELECT * FROM users WHERE age >= 18 AND (name = 'Alice' OR name = 'Bob');

Практические примеры Deferred

Когда нужна только часть полей:

# Загружаем только name и age, не загружаем bio (большой текст)
users = User.objects.defer('bio').all()

for user in users:
    print(user.name)  # OK, в памяти
    print(user.age)   # OK, в памяти
    print(user.bio)   # ❌ Дополнительный запрос!

Противоположное — only() загружает только нужные поля:

# Загружаем ТОЛЬКО name и age
users = User.objects.only('name', 'age').all()

for user in users:
    print(user.name)  # OK
    print(user.age)   # OK
    print(user.email) # ❌ Дополнительный запрос к БД

Сравнение defer и only:

# Если много полей, defer удобнее
User.objects.defer('large_text_field', 'another_large_field', 'third_large')

# Если нужна одна-две поля, only удобнее
User.objects.only('name', 'email')

Когда использовать что

Использовать filter когда:

  • Нужны только определённые записи (WHERE)
  • Сортировка и поиск
  • Объединение с другими таблицами (JOIN)
# Получить активных пользователей старше 18
active_adults = User.objects.filter(
    is_active=True,
    age__gte=18
).order_by('-created_at')

Использовать defer/only когда:

  • Есть большие текстовые поля (TextField, JSONField)
  • Нужно уменьшить объём данных из БД
  • Много записей (экономия памяти и трафика)
# Получить список пользователей, но не загружать большое описание
users = User.objects.defer('bio', 'large_photo').all()

# Если нужно значение bio, используй select_related
users = User.objects.filter(bio__isnull=False).values_list('name', 'bio')

Комбинирование filter и Deferred

Оптимальный запрос:

# Фильтруем по условию И выбираем только нужные поля
users = User.objects.filter(
    is_active=True,
    age__gte=18
).defer('large_bio_field').order_by('-created_at')

# SQL примерно:
# SELECT id, name, age, created_at FROM users 
# WHERE is_active = 1 AND age >= 18
# ORDER BY created_at DESC;

Отладка запросов

from django.db import connection
from django.test.utils import CaptureQueriesContext

# Посмотреть SQL запрос
users_qs = User.objects.filter(age__gte=18)
print(users_qs.query)  # SELECT ... WHERE age >= 18;

# Подсчитать количество запросов
with CaptureQueriesContext(connection) as queries:
    users = list(User.objects.defer('bio').all())
    for user in users:
        print(user.bio)  # Каждое обращение = новый запрос!

print(len(queries))  # Количество запросов
for query in queries:
    print(query['sql'])  # Каждый SQL запрос

Производительность

Пример: 1000 пользователей, каждый с bio 10KB

# ❌ Неоптимально: загружает 10MB данных
users = User.objects.all()  # SELECT * — загружает bio для всех

# ✅ Оптимально: загружает 100KB
users = User.objects.defer('bio').all()

# Если потом всё-таки нужна bio, это 1000 запросов
# Лучше использовать select_related для связей

Итоговая рекомендация

  • filter() — это WHERE, для выбора КАКИХ записей нужны
  • Deferred (defer/only) — это оптимизация SELECT, для выбора КАКИХ ПОЛЕЙ нужны
  • Сочетай оба: фильтруй записи AND выбирай нужные поля
  • Не забывай про select_related и prefetch_related для оптимизации связанных таблиц
В чём разница между фильтром и Deferred? | PrepBro