Сьогодні ми створимо наш перший ViewSet.
ViewSet — це клас у DRF, який можна використовувати для обробки різних HTTP-методів, таких як GET, POST, PUT, і DELETE. Тобто цей клас об'єднує логіку роботи з ресурсом в одному місці.
Стандартні методи для обробки CRUD-операцій:
- List: повернення списку об'єктів (аналогічно
GET /resources). - Retrieve: повернення даних одного об'єкта (аналогічно
GET /resources/{id}). - Create: створення нового об'єкта (аналогічно
POST /resources). - Update: оновлення існуючого об'єкта (аналогічно
PUT /resources/{id}). - Delete: видалення об'єкта (аналогічно
DELETE /resources/{id}).
Це дозволяє позбутися дублювання коду, яке характерне для створення окремих представлень для кожної операції.
Навіщо використовувати ViewSet?
Уявіть, що у вас є ресурс, скажімо, "Книги". Якщо ви плануєте створити API для керування цими книгами, то без ViewSet вам довелося б написати окремі функції для кожної дії:
- Список книг (
GET /books) - Отримання конкретної книги (
GET /books/{id}) - Додавання книги (
POST /books) - Оновлення книги (
PUT /books/{id}) - Видалення книги (
DELETE /books/{id})
ViewSet дозволяє об'єднати цю логіку в одному місці. Ну, це як супергерой у світі DRF — робить усе одразу і без зайвих заморочок.
Створення ViewSet
Крок 1: підготовка моделі
Перед тим як створити ViewSet, нам потрібно мати модель, з якою ми будемо працювати. Припустимо, що у нас є модель Book, яка представляє книги в нашій бібліотеці. Згадаємо її:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
published_date = models.DateField()
isbn = models.CharField(max_length=13)
pages = models.PositiveIntegerField()
def __str__(self):
return self.title
Крок 2: створення серіалізатора
Серіалізатор відповідає за перетворення даних між Python-об'єктами та JSON. Для нашого прикладу створимо BookSerializer:
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
Тут ми використовуємо ModelSerializer для автоматичної генерації полів на основі моделі Book. Це економить час і позбавляє нас від необхідності явно вказувати кожне поле.
Крок 3: створення ViewSet
Тепер час для головного героя сьогоднішнього дня — ViewSet! Ось як це робиться:
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
class BookViewSet(ViewSet):
"""
Простий ViewSet для управління книгами
"""
def list(self, request):
# Отримуємо всі книги з бази даних
books = Book.objects.all()
serializer = BookSerializer(books, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
# Отримуємо конкретну книгу за primary key (pk)
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) # HTTP 201 Created
return Response(serializer.errors, status=400) # HTTP 400 Bad Request
Цей ViewSet включає три методи:
list: повертає список усіх книг.retrieve: повертає конкретну книгу за їїid.create: дозволяє створити нову книгу.
Погодься, усе виглядає доволі лаконічно, так?
Підключення маршрутів через Router
Одного тільки ViewSet недостатньо. Нам потрібно зв'язати його з URL-адресами, щоб запити могли бути оброблені. Для цього в DRF є спеціальний клас — Router. Ось як це робиться:
from rest_framework.routers import DefaultRouter
from django.urls import path, include
from .views import BookViewSet
router = DefaultRouter()
router.register(r'books', BookViewSet, basename='book')
urlpatterns = [
path('', include(router.urls)),
]
За допомогою register ми реєструємо наш BookViewSet під маршрутом /books/. Тепер DRF автоматично створить маршрути для роботи з цим ресурсом. Приклад автоматично створених маршрутів:
GET /books/— список усіх книг.GET /books/{id}/— дані конкретної книги.POST /books/— створення нової книги.
Приклади запитів у Postman
- Отримати список книг:
Запит:
GET /books/
Відповідь:
[
{
"id": 1,
"title": "Гаррі Поттер і філософський камінь",
"author": "Дж. К. Роулінг",
"published_date": "1997-06-26",
"isbn": "9780747532699",
"pages": 223
},
{
"id": 2,
"title": "Війна і мир",
"author": "Лев Толстой",
"published_date": "1869-01-01",
"isbn": "9781234567890",
"pages": 1225
}
]
- Створити нову книгу:
Запит:
POST /books/
Content-Type: application/json
Тіло запиту:
{
"title": "1984",
"author": "Джордж Орвелл",
"published_date": "1949-06-08",
"isbn": "9780451524935",
"pages": 328
}
Відповідь:
{
"id": 3,
"title": "1984",
"author": "Джордж Орвелл",
"published_date": "1949-06-08",
"isbn": "9780451524935",
"pages": 328
}
Зворотний зв'язок і типові помилки
На цьому етапі можна зіткнутися з кількома проблемами. Наприклад, ви можете забути зареєструвати ViewSet у Router. У такому випадку будете отримувати помилки "404 Not Found" на всі запити, пов'язані з ресурсом.
Якщо ж ви отримуєте помилку "500 Server Error", скоріш за все, у коді є проблеми з серіалізатором або моделлю (наприклад, відсутнє потрібне поле isbn у базі даних). Переконайтеся, що структура моделі відповідає серіалізатору, і виконайте міграції після внесення змін до моделі.
Практичне застосування
Використання ViewSet у реальних проєктах дозволяє значно прискорити розробку API. Замість створення купи окремих представлень та маршрутів, ви отримуєте готовий інструмент для обробки CRUD-операцій. Це особливо зручно у великих проєктах з десятками (якщо не сотнями) моделей.
Плюс, на співбесідах часто обговорюють DRF, і розуміння того, як працюють ViewSet та Router, точно справить гарне враження.
На сьогодні все! Ми тільки почали знайомитися з ViewSet, але вже навчилися створювати базову структуру для ресурсу. У наступних лекціях ми заглибимося в тему і дізнаємося, як використовувати ModelViewSet та налаштовувати маршрутизацію більш гнучким чином.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ