В Django REST Framework, классы ViewSets, ModelViewSets и GenericViewSets что делают
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
ViewSets, ModelViewSets и GenericViewSets в Django REST Framework
Это ключевые компоненты DRF, которые упрощают разработку REST API. Они предоставляют различные уровни абстракции и автоматизации.
GenericViewSets
Это базовый класс, который комбинирует функциональность ViewSet с миксинами. Он не содержит никакой реализации actions (методов), но предоставляет механизм для их создания.
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
class ArticleViewSet(GenericViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
def list(self, request):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
GenericViewSet можешь расширить с помощью миксинов:
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.viewsets import GenericViewSet
class ArticleViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
# list() и retrieve() методы уже есть из миксинов!
ViewSet
Это базовый класс ViewSet, который не предоставляет никаких готовых методов. Используется когда тебе нужна полная гибкость:
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
class UserViewSet(ViewSet):
def list(self, request):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
user = User.objects.get(pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)
def create(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
В urls.py:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r"users", UserViewSet, basename="user")
urlpatterns = [
path("api/", include(router.urls)),
]
ModelViewSet
Это наиболее полнофункциональный класс, который автоматически предоставляет все CRUD операции (Create, Read, Update, Delete). Он комбинирует все необходимые миксины:
from rest_framework.viewsets import ModelViewSet
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
# Автоматически получаешь:
# - list() → GET /products/
# - create() → POST /products/
# - retrieve() → GET /products/{id}/
# - update() → PUT /products/{id}/
# - partial_update() → PATCH /products/{id}/
# - destroy() → DELETE /products/{id}/
Сравнительная таблица
| Класс | list | create | retrieve | update | destroy |
|---|---|---|---|---|---|
| ViewSet | Ручная реализация | Ручная | Ручная | Ручная | Ручная |
| GenericViewSet | С миксинами | С миксинами | С миксинами | С миксинами | С миксинами |
| ModelViewSet | ✅ | ✅ | ✅ | ✅ | ✅ |
Пример: Кастомизация ModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
class ArticleViewSet(ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
# Кастомное действие
@action(detail=True, methods=["post"])
def publish(self, request, pk=None):
article = self.get_object()
article.published = True
article.save()
return Response({"status": "article published"})
# GET /articles/{id}/publish/ → вызовет этот метод
def get_queryset(self):
"""Фильтровать в зависимости от пользователя"""
if self.request.user.is_superuser:
return Article.objects.all()
return Article.objects.filter(author=self.request.user)
Когда использовать
- ViewSet: максимальный контроль, сложная бизнес-логика
- GenericViewSet + миксины: баланс между гибкостью и удобством
- ModelViewSet: стандартный CRUD для моделей
Я на практике чаще всего использую ModelViewSet для быстрой разработки, а потом при необходимости переопределяю методы для специфической логики.