ViewSets & Routers
ViewSets bundle CRUD API endpoints; routers wire their URLs.
Syntax
router.register(r"posts", PostViewSet)A ViewSet groups the logic for a set of related endpoints (list, create, retrieve, update, destroy) into one class. A router then generates all the URLs for you automatically.
This gives you a complete RESTful API for a model in just a few lines.
Example
# blog/views.py
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
# blog/urls.py
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r"posts", PostViewSet)
urlpatterns = router.urlsWhen to use it
- A developer uses ModelViewSet to expose full CRUD operations for a Product resource with just a few lines.
- A team registers a ViewSet with a DefaultRouter to automatically generate all standard REST URLs.
- A developer adds a custom @action to a ViewSet to expose a non-standard endpoint like /posts/{id}/publish/.
More examples
ModelViewSet with router
Registers a ModelViewSet with a router to auto-generate list, detail, create, update, delete endpoints.
from rest_framework import viewsets
from rest_framework.routers import DefaultRouter
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
router = DefaultRouter()
router.register(r"posts", PostViewSet)
# urlpatterns = [path('api/', include(router.urls))]Read-only ViewSet
Uses ReadOnlyModelViewSet to expose only GET (list and detail) endpoints, no write operations.
from rest_framework import viewsets
class ProductViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Product.objects.filter(available=True)
serializer_class = ProductSerializerCustom action on a ViewSet
Adds a /posts/{pk}/publish/ endpoint via @action to handle a non-standard resource operation.
from rest_framework.decorators import action
from rest_framework.response import Response
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
@action(detail=True, methods=["post"])
def publish(self, request, pk=None):
post = self.get_object()
post.draft = False
post.save()
return Response({"status": "published"})
Discussion