На минулих заняттях ми занурилися у захопливий світ створення API з використанням Django REST Framework (DRF). Ми дізналися, що таке пагінація і чому вона важлива для нашої роботи, освоїли PageNumberPagination і LimitOffsetPagination, а також навчилися кастомізувати пагінацію під потреби нашого застосунку.
Ми почали розбирати фільтрацію даних і як вона дозволяє ефективно обробляти великі обсяги інформації. Настав час розкрити всю силу фільтрації і навчитися використовувати DjangoFilterBackend у наших представленнях API!
Що таке DjangoFilterBackend?
Фільтрація — це процес вибору підмножини даних на основі заданих критеріїв. Django REST Framework підтримує фільтрацію через сторонню бібліотеку django-filter, яка надає потужний і гнучкий спосіб фільтрувати дані у ваших API.
DRF має вбудовану підтримку фільтрації даних через DjangoFilterBackend, яка дозволяє пов'язувати параметри запиту і пошук даних через фільтри.
Офіційна документація django-filter: https://django-filter.readthedocs.io/
Встановлення та налаштування django-filter
Перед початком роботи нам потрібно встановити бібліотеку django-filter і додати її в наш проєкт.
Встановлення
Запустіть наступну команду для встановлення бібліотеки:
pip install django-filter
Після встановлення переконайтесь, що бібліотека додана до залежностей вашого проєкту (requirements.txt), щоб ваш колега або ви через 6 місяців не почали нервово шукати її.
# requirements.txt
django-filter
Реєстрація в налаштуваннях DRF
Потрібно повідомити Django і DRF про те, що ми будемо використовувати DjangoFilterBackend. Для цього додайте його в налаштування DEFAULT_FILTER_BACKENDS у файлі settings.py:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend', # Підключаємо DjangoFilterBackend
]
}
Тепер DRF знає, де шукати логіку фільтрації. Чудово, можна рухатися далі!
Підключення фільтрації до представлень API
Давайте підключимо модель для експериментів. Працювати ми будемо з моделлю, яка відображає каталог книг. Якщо її у вас немає, створіть її:
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
genre = models.CharField(max_length=100)
price = models.DecimalField(max_digits=6, decimal_places=2)
published_date = models.DateField()
def __str__(self):
return self.title
Не забудьте виконати міграції для створення таблиці в базі даних:
python manage.py makemigrations
python manage.py migrate
Для відображення даних створимо серіалізатор:
# serializers.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
Тепер додамо базовий ViewSet без фільтрації, щоб бачити повний список наших книг:
# views.py
from rest_framework.viewsets import ReadOnlyModelViewSet
from .models import Book
from .serializers import BookSerializer
class BookViewSet(ReadOnlyModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
Налаштуємо маршрутизацію:
# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BookViewSet
router = DefaultRouter()
router.register(r'books', BookViewSet, basename='book')
urlpatterns = [
path('', include(router.urls)),
]
Протестуйте /books/, і ви побачите всі доступні записи.
Налаштування фільтрації
Тепер ми підключимо DjangoFilterBackend і налаштуємо базову фільтрацію.
Додамо атрибут filterset_fields у наше представлення:
# views.py
from django_filters.rest_framework import DjangoFilterBackend
class BookViewSet(ReadOnlyModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend] # Вмикаємо фільтрацію
filterset_fields = ['author', 'genre', 'price'] # Вказуємо поля для фільтрації
Тепер ми можемо фільтрувати дані за переданими параметрами запиту. Наприклад:
/books/?author=J.K.%20Rowling— поверне всі книги автора "J.K. Rowling"./books/?genre=Fantasy&price=20.00— поверне фантастичні книги вартістю 20 доларів.
Кастомізація фільтрів
Іноді потрібна складна логіка фільтрації. Для цього ми можемо створити власний клас фільтрації.
Створіть файл filters.py у додатку, якщо його ще немає:
# filters.py
import django_filters
from .models import Book
class BookFilter(django_filters.FilterSet):
min_price = django_filters.NumberFilter(field_name='price', lookup_expr='gte')
max_price = django_filters.NumberFilter(field_name='price', lookup_expr='lte')
published_after = django_filters.DateFilter(field_name='published_date', lookup_expr='gte')
class Meta:
model = Book
fields = ['author', 'genre', 'min_price', 'max_price', 'published_after']
Тепер підключимо кастомний фільтр:
# views.py
from .filters import BookFilter
class BookViewSet(ReadOnlyModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = BookFilter # Вказуємо кастомний фільтр
З таким фільтром ваш API отримає додаткову функціональність. Наприклад:
/books/?min_price=10&max_price=30— книги в діапазоні цін від 10 до 30./books/?published_after=2021-01-01— книги, опубліковані після 2021 року.
Поради щодо фільтрації
- Перевіряйте продуктивність запитів. Фільтрація через базу даних працює швидше, ніж через Python, але складні запити можуть сповільнити API.
- Документуйте параметри фільтрації. Укажіть у документації API, які параметри доступні та які типи значень вони приймають.
- Використовуйте індексування. Додайте індекси до часто фільтрованих полів, щоб підвищити швидкість запитів.
Тепер ваш API став трохи розумнішим і готовий обробляти складні запити до даних. У наступній лекції ми розберемо, як організувати пошук і сортування даних в API, щоб користувачі могли знаходити потрібну інформацію ще швидше та зручніше.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ