Комментарии (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 для модели, с возможностью расширения и кастомизации под конкретные нужды.