JavaRush /Курси /Модуль 3: Django /Вступ до ViewSets

Вступ до ViewSets

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

Щоб зрозуміти, що таке ViewSet, уяви, що ти будуєш будинок. Якщо APIView — це цегла, з якої ти складаєш стіни, то ViewSet — це вже готовий модуль стіни з вікнами та дверима, який можна одразу вставити в будинок. Тобто ViewSet дозволяє об'єднувати в єдиний клас всю CRUD-логіку для роботи з моделлю.

ViewSet у DRF — це клас, який спрощує створення кількох обробників HTTP-запитів (GET, POST, PUT, DELETE) в одному місці. Замість написання окремих методів для кожної дії, ти можеш логічно зв'язати їх і реалізувати в одному класі.

Але не думай, що ViewSet зробить за тебе всю роботу! Тобі все одно доведеться писати бізнес-логіку. Просто тепер все буде більш структуровано.

Переваги використання ViewSet

  1. Єдина точка реалізації CRUD-операцій: ViewSet охоплює всю логіку для операцій створення, читання, оновлення та видалення записів (CRUD). Це спрощує та прискорює розробку.

  2. Спрощена маршрутизація: замість того, щоб вручну прописувати маршрути для кожного методу, ми можемо використовувати Router, який автоматично створює маршрути на основі ViewSet.

  3. Підвищення читабельності та масштабованості коду: вся поведінка API для однієї сутності зосереджена в одному місці — у класі ViewSet, що робить код більш акуратним і зручним для супроводу.

Структура ViewSet

На відміну від APIView, де ми писали методи типу get(), post() і так далі, ViewSet вже постачається з готовим набором методів:

  • list(self, request, *args, **kwargs) — обробка запитів для отримання списку об'єктів (аналог GET на рівні колекції, наприклад, /api/books/).
  • retrieve(self, request, *args, **kwargs) — обробка запитів для отримання одного об'єкта (аналог GET на рівні об'єкта, наприклад, /api/books/1/).
  • create(self, request, *args, **kwargs) — обробка запитів для створення нового об'єкта (аналог POST).
  • update(self, request, *args, **kwargs) — обробка запитів для повного оновлення об'єкта (аналог PUT).
  • partial_update(self, request, *args, **kwargs) — часткове оновлення об'єкта (аналог PATCH).
  • destroy(self, request, *args, **kwargs) — обробка запитів для видалення об'єкта (аналог DELETE).

Ці методи вже передбачені в DRF, і тобі залишається лише використовувати їх з розумом.

Як ViewSet об'єднує CRUD-логіку?

Коли ти створюєш ViewSet, ти описуєш всі операції для роботи з об'єктами однієї моделі в одному класі. Такий підхід робить код компактним і легко тестованим. Наприклад:

from rest_framework.viewsets import ViewSet
from rest_framework.response import Response

class BookViewSet(ViewSet):
    def list(self, request):
        # Логіка для обробки запиту GET /api/books
        return Response({"message": "Список всіх книг"})

    def retrieve(self, request, pk=None):
        # Логіка для обробки запиту GET /api/books/{id}
        return Response({"message": f"Отримання книги з id {pk}"})

    def create(self, request):
        # Логіка для обробки запиту POST /api/books
        return Response({"message": "Створення нової книги"})

    def update(self, request, pk=None):
        # Логіка для обробки запиту PUT /api/books/{id}
        return Response({"message": f"Оновлення книги з id {pk}"})

    def destroy(self, request, pk=None):
        # Логіка для обробки запиту DELETE /api/books/{id}
        return Response({"message": f"Видалення книги з id {pk}"})

Кожен метод відповідає за обробку свого запиту. Це або операція на рівні колекції (list, create), або на рівні окремого об'єкта (retrieve, update, destroy).

Приклад використання ViewSet

Давай подивимося, як ViewSet застосовується на практиці. Візьмемо за основу нашу модель Book.

# models.py
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=255)
    author = models.CharField(max_length=255)
    published_date = models.DateField()
    isbn = models.CharField(max_length=13, unique=True)

    def __str__(self):
        return self.title

Створимо відповідний серіалізатор для моделі:

# serializers.py
from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

Тепер створимо ViewSet для Book:

# views.py
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer

class BookViewSet(ViewSet):
    def list(self, request):
        books = Book.objects.all()
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        book = Book.objects.get(pk=pk)
        serializer = BookSerializer(book)
        return Response(serializer.data)

    def create(self, request):
        serializer = BookSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

    def update(self, request, pk=None):
        book = Book.objects.get(pk=pk)
        serializer = BookSerializer(book, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=400)

    def destroy(self, request, pk=None):
        book = Book.objects.get(pk=pk)
        book.delete()
        return Response(status=204)

Як підключити ViewSet до маршрутів?

Маршрути для ViewSet найпростіше налаштувати через Router. Завдяки цьому DRF сам подбає про створення маршрутів для list, retrieve та інших методів.

# 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)),
]

Тепер ці маршрути працюють «з коробки»:

  • GET /books → список книг.
  • GET /books/{id} → інформація про книгу.
  • POST /books → створення нової книги.
  • PUT /books/{id} → оновлення книги.
  • DELETE /books/{id} → видалення книги.

На що звернути увагу?

  1. Обробка виключень. Завжди обгортуй дії, такі як Book.objects.get(pk=pk), у try/except. Інакше, якщо об'єкт не знайдено, твій сервер повертатиме неінформативні 500-ки.
  2. Кастомізація методів. Якщо стандартних методів недостатньо, ти завжди можеш додати свої кастомні методи (про це пізніше на лекції 199).
  3. Продуктивність. Не забувай про оптимізацію запитів і використання select_related() або prefetch_related() при роботі з пов'язаними моделями.

ViewSets — це потужний інструмент, що дозволяє швидко створити API, зберігаючи при цьому код чистим і зручним. У наступних лекціях ми розберемо більш складні види ViewSet, такі як ModelViewSet, і навчимося налаштовувати маршрути через Router для максимальної гнучкості.

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