Сьогодні ми заглибимося у відмінності між класичними представленнями (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. Наприклад:
- list →
GET /example/ - retrieve →
GET /example/<id>/ - create →
POST /example/
Менше коду = менше помилок і головного болю.
Порівняння View та ViewSet
Тепер давайте розберемо основні відмінності між APIView та ViewSet.
- Обсяг коду
Уявімо, що ми хочемо реалізувати базові 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 (але це буде у наступних лекціях).
- Гнучкість
APIView забезпечує більший контроль над реалізацією. Вона краще підходить, якщо логіка відрізняється від стандартних CRUD-операцій. Наприклад, якщо ви хочете реалізувати якісь бізнес-операції (складні обчислення, нестандартні запити).
ViewSet, своєю чергою, спрощує створення API для стандартних CRUD-операцій, де все, що потрібно, вже "під капотом".
- Коли використовувати?
Використовуйте
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 твій найкращий друг.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ