JavaRush /Курси /Модуль 3: Django /Вступ до фільтрації даних у Django REST Framework

Вступ до фільтрації даних у Django REST Framework

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

Ми навчилися використовувати базові класи пагінації в DRF, такі як PageNumberPagination і LimitOffsetPagination, а також кастомізували їх для більш гнучкого налаштування. Звідси й плавно переходимо до нашої нової теми: фільтрація даних. Бо, знаєте, мало даних порційно віддавати — добре б ще давати користувачеві тільки те, що йому потрібно, а не "все і одразу".

Фільтрація у DRF

Django REST Framework (DRF) підтримує фільтрацію даних прямо "з коробки". У DRF для фільтрації вже підготовлені механізми, такі як DjangoFilterBackend, SearchFilter і OrderingFilter. Ці інструменти можна комбінувати, щоб не просто фільтрувати дані, але й сортувати їх за полями API, а також шукати за конкретними значеннями. Ми почнемо з основ, а потім будемо рухатися до більш складних і кастомних сценаріїв.

Найпростіша ручна фільтрація

Почнемо з базового прикладу. Якщо раптом тобі не потрібно використовувати готові інструменти фільтрації або ти хочеш реалізувати щось просте, можна додати фільтрацію прямо в метод твого представлення.

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Product

class ProductListView(APIView):
    def get(self, request):
        # Отримуємо необроблені дані з моделі
        products = Product.objects.all()

        # Перевіряємо, чи є параметр фільтрації "category"
        category = request.query_params.get('category')
        if category:
            products = products.filter(category=category)

        # Перетворюємо дані в Python, щоб віддати їх клієнту
        data = [{"id": p.id, "name": p.name, "category": p.category} for p in products]
        return Response(data)

Тут відбувається наступне:

  1. Ми беремо всі записи з моделі Product.
  2. Перевіряємо, чи передав користувач параметр category у рядку запиту (?category=some-category).
  3. Якщо параметр є, фільтруємо дані за категорією.

Досить просто, чи не так? Однак якщо ти хочеш додати більше можливостей фільтрації, наприклад, фільтр за ціною, назвою, виробником, то твій код швидко перетвориться на кашу з умов. Тому для масштабованості краще звернутися за допомогою до інструментів DRF.

Підтримка фільтрації в DRF

DjangoFilterBackend— це вбудований інструмент DRF для роботи з фільтрацією. Він дозволяє підключити фільтрацію на рівні представлень і використовувати готові фільтри, які визначаються через спеціальні класи. Це робить код чистішим і дозволяє зосередитися на логіці.

Перш ніж ми почнемо з налаштування, переконайтеся, що у вас встановлена бібліотека django-filter. Якщо не встановлена, то вам на допомогу приходить команда:

pip install django-filter

Потім додайте django_filters до списку INSTALLED_APPS вашого settings.py:

INSTALLED_APPS = [
    # Інші додатки
    'django_filters',
]

Вуаля, тепер ми готові до фільтрації!

Налаштування фільтрації з DjangoFilterBackend

Для початку підключимо DjangoFilterBackend до нашого проєкту. У DRF бекенди фільтрації визначаються у налаштуванні DEFAULT_FILTER_BACKENDS у settings.py:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
    ],
}

Це дозволяє задавати фільтри в будь-якому з ваших представлень.

Проста фільтрація

Використовуємо DjangoFilterBackend у нашому представленні. Припустимо, у нас є модель Product:

# models.py
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    category = models.CharField(max_length=50)
    price = models.DecimalField(max_digits=10, decimal_places=2)

Тепер додамо фільтрацію у представлення:

# views.py
from rest_framework.generics import ListAPIView
from django_filters.rest_framework import DjangoFilterBackend
from .models import Product
from .serializers import ProductSerializer

class ProductListView(ListAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    filter_backends = [DjangoFilterBackend]  # Підключаємо бекенд фільтрації
    filterset_fields = ['category', 'price']  # Вказуємо доступні поля фільтрації

Тепер ви можете звертатися до API за допомогою таких запитів:

  • GET /api/products?category=electronics—отримати всі продукти у категорії "electronics".
  • GET /api/products?price=99.99—отримати всі продукти з ціною 99.99.

Як бачите, все вже працює! А ще код став чистішим, ніж у нашому базовому прикладі.

Кастомізація фільтрації з FilterSet

Якщо потрібно більше контролю над логікою фільтрації, можна створювати кастомні набори фільтрів (filter sets), використовуючи бібліотеку django-filter.

# filters.py
import django_filters
from .models import Product

class ProductFilter(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')

    class Meta:
        model = Product
        fields = ['category', 'min_price', 'max_price']

Ми додали два кастомні фільтри: min_price (ціна більше або дорівнює) і max_price (ціна менше або дорівнює). Тепер підключимо ці фільтри в нашому представленні:

# views.py
from .filters import ProductFilter

class ProductListView(ListAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = ProductFilter  # Вказуємо наш кастомний клас фільтрів

Тепер доступні фільтри на зразок:

  • GET /api/products?min_price=50&max_price=200—продукти з ціною між 50 і 200.
  • GET /api/products?category=books&min_price=10—книги з ціною від 10.

Підказка про налагодження фільтрів

Одна з типових проблем при роботі з фільтрацією — це відсутність даних, тому що фільтр не спрацював. Якщо бачиш порожній список результатів, перш за все перевір:

  1. Що параметр фільтрації передається коректно ?category=something.
  2. Що дані в базі відповідають значенню фільтра.

Якщо щось не сходиться, спробуй налагодити запит на стороні Django ORM: візьми отриманий QuerySet і виконай його у Django shell.

Переваги підходу

Фільтрація за допомогою DjangoFilterBackend значно спрощує життя:

  • Чистий і зрозумілий код.
  • Потужні можливості кастомізації.
  • Швидка інтеграція фільтрів в API.

Рухаючись далі, ми заглибимось у додаткові можливості, такі як пошук, сортування та кастомні фільтри. Ми тільки почали розкривати потенціал фільтрації!

3
Опитування
Вступ до пагінації в DRF, рівень 19, лекція 4
Недоступний
Вступ до пагінації в DRF
Вступ до пагінації в DRF
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ