Ответ
ViewSet в DRF — это класс, который объединяет логику для набора связанных представлений (views) в одном месте. Вместо того чтобы создавать отдельные классы для операций чтения списка, создания, получения, обновления и удаления объекта, вы можете определить один ViewSet.
Основная цель ViewSet — уменьшить количество повторяющегося кода (boilerplate) и следовать принципу DRY (Don't Repeat Yourself). Его настоящая сила раскрывается при использовании вместе с Routers, которые автоматически генерируют URL-паттерны.
Основные составляющие ViewSet:
-
Стандартные действия (Actions): Методы, которые сопоставляются с HTTP-запросами при использовании роутера:
.list()(GET-запрос на список).create()(POST-запрос).retrieve()(GET-запрос на один объект).update()(PUT-запрос).partial_update()(PATCH-запрос).destroy()(DELETE-запрос)
-
Ключевые атрибуты:
queryset: Набор объектов, с которыми будет работатьViewSet.serializer_class: Класс сериализатора для преобразования данных.
-
Пользовательские действия: Можно добавлять собственные эндпоинты с помощью декоратора
@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?
-
Стандартные экшены (actions) — это методы, которые уже зашиты внутрь и которые роутер сам привязывает к HTTP-запросам:
.list()— это когда GET-запрос на список всех объектов (например,/books/)..create()— это POST, чтобы новый объект создать..retrieve()— это GET, но для одного конкретного объекта по ID (/books/5/)..update()— PUT, чтобы всё разом поменять..partial_update()— PATCH, чтобы только кусочек обновить..destroy()— DELETE, ну тут всё ясно, отправить нахуй объект.
-
Главные атрибуты, без которых нихуя не работает:
queryset— говоришь ему, откуда данные тащить (типаBook.objects.all()).serializer_class— указываешь, какой сериализатор будет превращать твои модели в JSON и обратно.
-
Свои, кастомные экшены — а это вообще песня! Если тебе мало стандартного 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}/
# И всё это — из одной строчки регистрации! Вообще ебушки-воробушки.
Вот и вся философия. Не городи велосипеды, не повторяй код, используй готовые мощные абстракции. А то будешь как тот Герасим из «Муму» — сильный, молчаливый, но нихуя не эффективный, блядь.