Сегодня мы создадим наш первый 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 и настраивать маршрутизацию более гибким образом.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ