JavaRush /Курси /Модуль 3: Django /Відмінності між View та ViewSet

Відмінності між View та ViewSet

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

Сьогодні ми заглибимося у відмінності між класичними представленнями (View або APIView) та їх більш потужним і зручним "колегою" — ViewSet. Ми порівняємо їх функціонал, обговоримо, коли краще використовувати той чи інший підхід, і, звісно, розглянемо приклади.

View (або APIView): базовий функціонал

Почнемо з класичних представлень. Це як фундаментальний інструмент для створення API в DRF: він простий, зручний, але вимагає від розробника більше коду, якщо вам потрібно реалізувати кілька дій для одного й того ж ресурсу.

APIView — це DRF-шний аналог стандартного Django-класу View. Він дає нам доступ до:

  • Методу request для обробки HTTP-запитів (GET, POST, PUT, DELETE та ін.).
  • Вбудованої обробки серіалізації даних.
  • Простого способу повернення HTTP-відповідей.

Приклад базового APIView:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class ExampleView(APIView):
    def get(self, request):
        # Логіка обробки GET запиту
        data = {"message": "Привіт, світе!"}
        return Response(data, status=status.HTTP_200_OK)

    def post(self, request):
        # Логіка обробки POST запиту
        data = {"message": "Ви надіслали дані:", "data": request.data}
        return Response(data, status=status.HTTP_201_CREATED)

Приклад вище простий і зрозумілий, але якщо нам потрібно додати більше операцій (наприклад, PUT, DELETE), це вимагатиме додаткового коду і тестування.

ViewSet: Потужність і зручність

Тепер перейдемо до ViewSet. Це як універсальний швейцарський ніж для створення API: він дозволяє спростити написання коду, об'єднуючи всі CRUD-операції в одному місці.

1. Що таке ViewSet?

ViewSet — це абстракція, яка об'єднує всі CRUD-операції в одному класі. Замість того щоб писати окремі методи для кожного HTTP-методу (get, post, put і т.д.), ви описуєте свої дії в одному місці, а DRF сам створює маршрути для вашого API.

Приклад базового ViewSet:

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

class ExampleViewSet(ViewSet):
    def list(self, request):
        # GET запит на отримання списку об'єктів
        data = {"message": "Список даних"}
        return Response(data)

    def retrieve(self, request, pk=None):
        # GET запит для отримання одного об'єкта за його ID
        data = {"message": f"Дані для об'єкта {pk}"}
        return Response(data)

    def create(self, request):
        # POST запит для створення нового об'єкта
        data = {"message": "Створено новий об'єкт", "data": request.data}
        return Response(data)

Тут DRF автоматично створює маршрути для дій list, retrieve і create. Наприклад:

  • listGET /example/
  • retrieveGET /example/<id>/
  • createPOST /example/

Менше коду = менше помилок і головного болю.

Порівняння View та ViewSet

Тепер давайте розберемо основні відмінності між APIView та ViewSet.

  1. Обсяг коду

Уявімо, що ми хочемо реалізувати базові CRUD-операції (створення, читання, оновлення, видалення) для ресурсу "Книги". Приклад через APIView:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class BookListView(APIView):
    def get(self, request):
        # Повертаємо список книг
        data = {"books": ["Книга 1", "Книга 2"]}
        return Response(data)

    def post(self, request):
        # Створюємо нову книгу
        data = {"message": "Книга створена"}
        return Response(data, status=status.HTTP_201_CREATED)

class BookDetailView(APIView):
    def get(self, request, pk):
        # Отримуємо дані книги за ID
        data = {"book": f"Дані для книги {pk}"}
        return Response(data)

    def put(self, request, pk):
        # Оновлюємо дані книги
        data = {"message": f"Книга {pk} оновлена"}
        return Response(data)

    def delete(self, request, pk):
        # Видаляємо книгу
        data = {"message": f"Книга {pk} видалена"}
        return Response(data, status=status.HTTP_204_NO_CONTENT)

Ми розділили логіку на два класи: BookListView та BookDetailView. Так, усе працює, але вийшло багатослівно. А тепер, той самий функціонал на ViewSet:

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

class BookViewSet(ViewSet):
    def list(self, request):
        # GET /books/
        data = {"books": ["Книга 1", "Книга 2"]}
        return Response(data)

    def create(self, request):
        # POST /books/
        data = {"message": "Книга створена"}
        return Response(data)

    def retrieve(self, request, pk=None):
        # GET /books/<pk>/
        data = {"book": f"Дані для книги {pk}"}
        return Response(data)

    def update(self, request, pk=None):
        # PUT /books/<pk>/
        data = {"message": f"Книга {pk} оновлена"}
        return Response(data)

    def destroy(self, request, pk=None):
        # DELETE /books/<pk>/
        data = {"message": f"Книга {pk} видалена"}
        return Response(data)

Код коротший, а маршрути налаштовуються автоматично. Наприклад, замість ручного прописування URL ми можемо використовувати маршрутизатори Router (але це буде у наступних лекціях).

  1. Гнучкість

APIView забезпечує більший контроль над реалізацією. Вона краще підходить, якщо логіка відрізняється від стандартних CRUD-операцій. Наприклад, якщо ви хочете реалізувати якісь бізнес-операції (складні обчислення, нестандартні запити).

ViewSet, своєю чергою, спрощує створення API для стандартних CRUD-операцій, де все, що потрібно, вже "під капотом".

  1. Коли використовувати?
  • Використовуйте APIView або View, якщо:

    • У вас специфічні вимоги до реалізації ендпоінта.
    • Ви хочете гнучко керувати логікою обробки запитів.
  • Використовуйте ViewSet, якщо:

    • Вам потрібно швидко створити API для стандартних CRUD-операцій.
    • Ви працюєте з серіалізаторами та стандартними методами роботи з моделями.

Приклади вибору між View та ViewSet

Сценарій 1: простий перегляд даних. Якщо API потрібен лише для простого перегляду даних (створення, читання, оновлення, видалення), ViewSet — ваш вибір. Він зменшує кількість коду та автоматизує маршрутизацію.

Сценарій 2: Кастомна логіка. Якщо у вас складні операції, які не вписуються в CRUD, наприклад, обробка великих файлів, окремі класи на основі APIView підійдуть краще. Наприклад:

class FileUploadView(APIView):
    def post(self, request):
        # Логіка завантаження файлу
        file = request.FILES['file']
        process_file(file)  # Припустимо, ви обробляєте файл
        return Response({"message": "Файл оброблено"})

TL;DR: Хто кращий?

Якщо ти створюєш CRUD API для ресурсу — ViewSet скоротить час і позбавить від зайвого шаблонного коду. Якщо тобі потрібно більше гнучкості або кастомної логіки — APIView твій найкращий друг.

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