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 ваш лучший друг.

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