JavaRush /Курсы /Модуль 3: Django /Фильтрация данных в QuerySet

Фильтрация данных в QuerySet

Модуль 3: Django
8 уровень , 3 лекция
Открыта

Вы уже знаете, что 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: Использование операторов

  1. Совпадение по части строки:

Мы хотим найти все книги, в названии которых есть слово "Гордость":

books_with_pride = Book.objects.filter(title__icontains="гордость")
  1. Фильтрация по диапазону:

Мы ищем книги, опубликованные после 2000 года:

recent_books = Book.objects.filter(publish_year__gte=2000)
  1. Проверка на 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: фильтрация записей

  1. Создайте модель Movie с полями:

    • title (строка)
    • genre (строка)
    • release_year (целое число)
    • rating (дробное число)
  2. Заполните базу данных не менее чем 5 фильмами.

  3. Выполните следующие запросы:

    • Найдите все фильмы жанра "комедия".
    • Найдите все фильмы, выпущенные до 2000 года.
    • Найдите фильмы с рейтингом выше 8.0.
    • Найдите фильмы, жанр которых начинается с буквы "д".

Задание 2: совмещение условий

Для модели Movie:

  • Найдите все фильмы, жанр которых "комедия" или рейтинг больше 9.0.
  • Исключите фильмы, выпущенные раньше 2010 года.

Подсказка: используйте Q-объекты.

Теперь вы знаете, как эффективно фильтровать данные в Django ORM! Готовьтесь, впереди ещё больше возможностей!

1
Задача
Модуль 3: Django, 8 уровень, 3 лекция
Недоступна
Фильтрация по нескольким условиям
Фильтрация по нескольким условиям
1
Задача
Модуль 3: Django, 8 уровень, 3 лекция
Недоступна
Усложнённая фильтрация с подстроками
Усложнённая фильтрация с подстроками
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ