На прошлых занятиях мы погрузились в увлекательный мир создания 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, чтобы пользователи могли находить нужную информацию ещё быстрее и удобнее.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ