Ви вже знаєте, що 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! Готуйтеся, попереду ще більше можливостей!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ