Что такое ViewSet в Django REST Framework и из чего он состоит?

Ответ

ViewSet в DRF — это класс, который объединяет логику для набора связанных представлений (views) в одном месте. Вместо того чтобы создавать отдельные классы для операций чтения списка, создания, получения, обновления и удаления объекта, вы можете определить один ViewSet.

Основная цель ViewSet — уменьшить количество повторяющегося кода (boilerplate) и следовать принципу DRY (Don't Repeat Yourself). Его настоящая сила раскрывается при использовании вместе с Routers, которые автоматически генерируют URL-паттерны.

Основные составляющие ViewSet:

  1. Стандартные действия (Actions): Методы, которые сопоставляются с HTTP-запросами при использовании роутера:

    • .list() (GET-запрос на список)
    • .create() (POST-запрос)
    • .retrieve() (GET-запрос на один объект)
    • .update() (PUT-запрос)
    • .partial_update() (PATCH-запрос)
    • .destroy() (DELETE-запрос)
  2. Ключевые атрибуты:

    • queryset: Набор объектов, с которыми будет работать ViewSet.
    • serializer_class: Класс сериализатора для преобразования данных.
  3. Пользовательские действия: Можно добавлять собственные эндпоинты с помощью декоратора @action.

Пример ModelViewSet (предоставляет полный CRUD):

from rest_framework import viewsets, permissions, routers
from .models import Book
from .serializers import BookSerializer

# ViewSet объединяет всю логику для модели Book
class BookViewSet(viewsets.ModelViewSet):
    """
    Этот ViewSet автоматически предоставляет действия `list`, `create`, `retrieve`,
    `update`, `partial_update` и `destroy` для модели Book.
    """
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [permissions.IsAuthenticated]

# В файле urls.py роутер создаст все необходимые URL-адреса
router = routers.DefaultRouter()
router.register(r'books', BookViewSet)

# Будут сгенерированы URL-ы, такие как:
# /books/ (GET, POST)
# /books/{id}/ (GET, PUT, PATCH, DELETE)

Ответ 18+ 🔞

А, ViewSet в DRF, ну это ж классика, блядь! Слушай, представь себе такую хуйню: ты пишешь API, и каждый раз для одной и той же сущности — книжки там, пользователи, котики — тебе надо городить пять отдельных классов-вьюх. Один список выводит, другой создаёт, третий удаляет... Пиздец, какой boilerplate, одно и то же по сто раз переписывать! Руки отсохнуть могут, ей-богу.

И тут приходит он, ёпта, ViewSet — такой мужик с бородой, который говорит: «Зачем распыляться, чувак? Давай всё в одну кучу, в один класс!». И вся логика для всех операций над одной моделью — list, create, retrieve, update, delete — живёт в одном месте. Красота же!

Но настоящая магия, блядь, начинается, когда ты подключаешь к нему Router. Это такой хитрожопый автомат, который смотрит на твой ViewSet и сам, на автомате, генерирует все нужные URL-адреса. Не надо вручную в urls.py прописывать кучу строк. Роутер сам сделает /books/, /books/1/ и всё прикрутит. Просто сказка, в рот меня чих-пых!

Из чего же, из чего же сделан наш ViewSet?

  1. Стандартные экшены (actions) — это методы, которые уже зашиты внутрь и которые роутер сам привязывает к HTTP-запросам:

    • .list() — это когда GET-запрос на список всех объектов (например, /books/).
    • .create() — это POST, чтобы новый объект создать.
    • .retrieve() — это GET, но для одного конкретного объекта по ID (/books/5/).
    • .update() — PUT, чтобы всё разом поменять.
    • .partial_update() — PATCH, чтобы только кусочек обновить.
    • .destroy() — DELETE, ну тут всё ясно, отправить нахуй объект.
  2. Главные атрибуты, без которых нихуя не работает:

    • queryset — говоришь ему, откуда данные тащить (типа Book.objects.all()).
    • serializer_class — указываешь, какой сериализатор будет превращать твои модели в JSON и обратно.
  3. Свои, кастомные экшены — а это вообще песня! Если тебе мало стандартного CRUD, ты можешь навесить на свой ViewSet любую дополнительную хуйню. Например, эндпоинт /books/best-sellers/. Делается это через декоратор @action. Охуенно удобно!

Смотри, как это выглядит в коде, на примере ModelViewSet (это самый полный и жирный вариант):

from rest_framework import viewsets, permissions, routers
from .models import Book
from .serializers import BookSerializer

# Весь цирк с книжками — в одном классе! Никакой лишней писанины.
class BookViewSet(viewsets.ModelViewSet):
    """
    Этот ViewSet — просто машина, блядь. Сам всё сделает: список, создание,
    просмотр одной, обновление, частичное обновление и удаление в пизду.
    Всё для модели Book.
    """
    queryset = Book.objects.all()  # Говорим, с чем работаем
    serializer_class = BookSerializer  # Говорим, как преобразовываем
    permission_classes = [permissions.IsAuthenticated]  # Чтоб не всякий левый мог

# А в urls.py — вообще красота, один роутер и всё!
router = routers.DefaultRouter()
router.register(r'books', BookViewSet)  # Регистрируем наш ViewSet

# И роутер, этот хитрожопый гений, сам нагенерит URL-ы:
# GET, POST на /books/
# GET, PUT, PATCH, DELETE на /books/{id}/
# И всё это — из одной строчки регистрации! Вообще ебушки-воробушки.

Вот и вся философия. Не городи велосипеды, не повторяй код, используй готовые мощные абстракции. А то будешь как тот Герасим из «Муму» — сильный, молчаливый, но нихуя не эффективный, блядь.