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 для максимальной гибкости.

1
Задача
Модуль 3: Django, 20 уровень, 0 лекция
Недоступна
Создание базового ViewSet
Создание базового ViewSet
1
Задача
Модуль 3: Django, 20 уровень, 0 лекция
Недоступна
Реализация методов для CRUD-операций
Реализация методов для CRUD-операций
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ