JavaRush /Курси /Модуль 3: Django /Використання DjangoFilterBackend

Використання DjangoFilterBackend

Модуль 3: Django
Рівень 19 , Лекція 5
Відкрита

На минулих заняттях ми занурилися у захопливий світ створення 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, щоб користувачі могли знаходити потрібну інформацію ще швидше та зручніше.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ