Вы уже знаете, что QuerySet — это мощный инструмент для взаимодействия с базой данных в Django. Мы научились создавать объекты через модель, они магически сохраняются в базе — ну почти магически, ведь мы сами все написали. Также мы обсудили, как извлекать данные с помощью методов all() и работать с ними. Теперь настало время добавить немного фильтров — потому что не всё, что лежит в базе, вам нужно, а искать только одно нужное среди миллиона записей — ну такое себе удовольствие.
1. Основы фильтрации
Что такое filter()?
Представьте, что QuerySet — это как гигантское озеро данных. Метод filter() — это тот сачок, которым мы выбираем только те данные, которые удовлетворяют нашим требованиям. Это основной способ отбора данных из базы на уровне ORM.
С помощью фильтрации мы можем:
- Создавать простые запросы для отбора по конкретному значению поля.
- Задавать сложные условия с помощью операторов.
- Комбинировать и объединять несколько фильтров.
Метод filter() возвращает новый QuerySet, содержащий только те объекты, которые соответствуют условиям фильтрации.
Синтаксис:
Model.objects.filter(<условие>)
Основной принцип: вы передаёте в filter() условия в виде ключевых аргументов, где ключ — это название поля модели, а значение — искомое значение.
Пример 1: Простая фильтрация
Допустим, у нас есть модель Book:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
publish_year = models.IntegerField()
is_available = models.BooleanField(default=True)
Теперь вы хотите получить все книги автора "Джейн Остин":
from myapp.models import Book
# Получаем все книги автора "Джейн Остин"
books_by_jane_austen = Book.objects.filter(author="Джейн Остин")
Переменная books_by_jane_austen содержит все книги, у которых в поле author указано "Джейн Остин".
Использование операторов фильтрации
Django ORM предоставляет удобные операторы фильтрации, которые могут быть применены к значениям полей. Например:
| Оператор | Описание | Пример использования |
|---|---|---|
__exact |
Точное совпадение | author__exact="Джейн Остин" |
__iexact |
Точное совпадение без учёта регистра | author__iexact="джЕйн ОстИн" |
__contains |
Проверка, содержит ли поле подстроку | title__contains="Гордость" |
__icontains |
То же, но без учёта регистра | title__icontains="гордость" |
__gte |
Больше или равно | publish_year__gte=2000 |
__lte |
Меньше или равно | publish_year__lte=1999 |
__in |
Совпадение с одним из указанных значений | author__in=["Джейн Остин", "Толстой"] |
__isnull |
Проверка на NULL |
is_available__isnull=True |
Пример 2: Использование операторов
- Совпадение по части строки:
Мы хотим найти все книги, в названии которых есть слово "Гордость":
books_with_pride = Book.objects.filter(title__icontains="гордость")
- Фильтрация по диапазону:
Мы ищем книги, опубликованные после 2000 года:
recent_books = Book.objects.filter(publish_year__gte=2000)
- Проверка на
NULL:
Иногда поле может быть пустым (например, автор неизвестен). Чтобы найти такие записи:
books_with_unknown_author = Book.objects.filter(author__isnull=True)
Сложные условия фильтрации
Что делать, если вы хотите объединить несколько условий? Например, надо найти книги, у которых автор "Джейн Остин" и название содержит "разум".
Комбинирование условий с filter()
При использовании нескольких условий в одном вызове filter() они объединяются с помощью логического оператора И.
books_by_jane_and_reason = Book.objects.filter(
author="Джейн Остин",
title__icontains="разум"
)
Этот запрос вернёт книги, удовлетворяющие обоим условиям.
Использование Q-объектов для сложных условий
Иногда вам нужно создать более сложный запрос, например:
- - Найти книги, у которых автор "Джейн Остин" или название содержит "разум".
Для таких случаев используется класс Q из django.db.models.
Работа с Q
С помощью Q можно комбинировать условия с помощью операторов И & и ИЛИ |.
from django.db.models import Q
books_by_jane_or_reason = Book.objects.filter(
Q(author="Джейн Остин") | Q(title__icontains="разум")
)
Обратите внимание, что здесь логическое ИЛИ (|) объединяет оба условия.
Пример: отрицание условия
С помощью ~ (тильды) можно отрицать условие. Например, если хотите исключить книги автора "Джейн Остин":
not_by_jane = Book.objects.filter(~Q(author="Джейн Остин"))
Лучшие практики при фильтрации
Используйте ленивую загрузку QuerySet: QuerySet не выполняет запрос к базе данных сразу. Это позволяет вам добавлять фильтры и изменять запрос до его явного выполнения.
Оптимизируйте сложные запросы: если вы используете много условий, убедитесь, что они выполняются эффективно. Используйте встроенные методы Django, такие как
select_related()илиprefetch_related(), если работаете с связанными объектами.Не бойтесь пробовать! ORM Django дружелюбна и прощает многие ваши эксперименты. Только не используйте спутниками продакшн для таких экспериментов.
Практика
Задание 1: фильтрация записей
Создайте модель
Movieс полями:title(строка)genre(строка)release_year(целое число)rating(дробное число)
Заполните базу данных не менее чем 5 фильмами.
Выполните следующие запросы:
- Найдите все фильмы жанра "комедия".
- Найдите все фильмы, выпущенные до 2000 года.
- Найдите фильмы с рейтингом выше 8.0.
- Найдите фильмы, жанр которых начинается с буквы "д".
Задание 2: совмещение условий
Для модели Movie:
- Найдите все фильмы, жанр которых "комедия" или рейтинг больше 9.0.
- Исключите фильмы, выпущенные раньше 2010 года.
Подсказка: используйте Q-объекты.
Теперь вы знаете, как эффективно фильтровать данные в Django ORM! Готовьтесь, впереди ещё больше возможностей!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ