← Назад к вопросам

Что такое ModelViewSet?

3.0 Senior🔥 81 комментариев
#DevOps и инфраструктура#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

ModelViewSet в Django REST Framework

Определение

ModelViewSet — это мощный класс в Django REST Framework, который автоматически генерирует стандартные CRUD операции (Create, Read, Update, Delete) для работы с моделями Django. Это комбинация ViewSet + Generic Views.

Что включает ModelViewSet

МодельViewSet автоматически создаёт следующие методы и endpoints:

from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

Одна регистрация в urls.py создаёт ВСЕ эти endpoints:

GET    /articles/              # Список (list)
POST   /articles/              # Создание (create)
GET    /articles/{id}/         # Получение одного (retrieve)
PUT    /articles/{id}/         # Полное обновление (update)
PATCH  /articles/{id}/         # Частичное обновление (partial_update)
DELETE /articles/{id}/         # Удаление (destroy)

Полный пример

1. Модель Django

from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return self.title

2. Сериализатор

from rest_framework import serializers
from .models import Article

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ["id", "title", "content", "author", "created_at"]

3. ViewSet

from rest_framework import viewsets, permissions
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

4. URLs

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet

router = DefaultRouter()
router.register(r"articles", ArticleViewSet, basename="article")

urlpatterns = [
    path("api/", include(router.urls)),
]

Типы ViewSet

ReadOnlyModelViewSet

Только для чтения (GET):

class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    # Доступны: list(), retrieve()

ModelViewSet (полный CRUD)

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    # Доступны: list(), create(), retrieve(), update(), partial_update(), destroy()

Переопределение методов

from rest_framework.response import Response
from rest_framework import status

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    
    # Переопределение list()
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
    
    # Переопределение create()
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    
    # Переопределение destroy()
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)
    
    # Выполнение действия при создании
    def perform_create(self, serializer):
        serializer.save(author=self.request.user)
    
    # Выполнение действия при обновлении
    def perform_update(self, serializer):
        serializer.save()

Кастомные actions

from rest_framework.decorators import action
from rest_framework.response import Response

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    
    # GET /articles/{id}/publish/
    @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/recent/
    @action(detail=False, methods=["get"])
    def recent(self, request):
        recent_articles = Article.objects.order_by("-created_at")[:10]
        serializer = self.get_serializer(recent_articles, many=True)
        return Response(serializer.data)

Фильтрация, поиск и сортировка

from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    
    # Фильтрация: /articles/?author=John
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ["author", "created_at"]
    search_fields = ["title", "content"]
    ordering_fields = ["created_at", "title"]
    ordering = ["-created_at"]

Pagination (Пагинация)

from rest_framework.pagination import PageNumberPagination

class CustomPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = "page_size"
    max_page_size = 100

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    pagination_class = CustomPagination

Permissions (Права доступа)

from rest_framework import permissions

class IsAuthorOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.author == request.user

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = [IsAuthorOrReadOnly]

Сравнение подходов

ПодходКодГибкость
Generic ViewsМного кодаВысокая
ViewSetСреднее количествоСредняя
ModelViewSetМинимум кодаНизкая (но расширяемая)

Преимущества ModelViewSet

  • DRY принцип: один класс = все CRUD операции
  • Автоматическая регистрация маршрутов: Router генерирует все URLs
  • Встроенная валидация: через ModelSerializer
  • Встроенные permissions и filters: легко добавить
  • Расширяемость: можно переопределить любой метод

Недостатки

  • Меньше контроля: если нужна сложная бизнес-логика
  • Все 6 операций: если нужны только некоторые, лучше использовать ViewSet
  • Сложнее тестировать: много скрытого кода

Итоговая схема

ModelViewSet — это готовое решение для CRUD операций в Django REST Framework. Один класс + одна строка в роутере = полноценное REST API для модели, с возможностью расширения и кастомизации под конкретные нужды.

Что такое ModelViewSet? | PrepBro