ViewSets, that allows the developer to concentrate on modeling the state and interactions of the API, and leave the URL construction to be handled automatically, based on common conventions.
ViewSet classes are almost the same thing as View classes, except that they provide operations such as retrieve, or update, and not method handlers such as get or put.
A ViewSet class is only bound to a set of method handlers at the last moment, when it is instantiated into a set of views, typically by using a Router class which handles the complexities of defining the URL conf for you.
Refactoring to use ViewSets
Let’s take our current set of views, and refactor them into view sets. First of all let’s refactor ourUserList and UserDetail classes into a single UserViewSet class. In the snippets/views.py file, we can remove the two view classes and replace them with a single ViewSet class:
snippets/views.py
ReadOnlyModelViewSet class to automatically provide the default ‘read-only’ operations. We’re still setting the queryset and serializer_class attributes exactly as we did when we were using regular views, but we no longer need to provide the same information to two separate classes.
Next we’re going to replace the SnippetList, SnippetDetail and SnippetHighlight view classes. We can remove the three views, and again replace them with a single class.
snippets/views.py
ModelViewSet class in order to get the complete set of default read and write operations.
Notice that we’ve also used the @action decorator to create a custom action, named highlight. This decorator can be used to add any custom endpoints that don’t fit into the standard create/update/delete style.
Custom actions which use the @action decorator will respond to GET requests by default. We can use the methods argument if we wanted an action that responded to POST requests.
The URLs for custom actions by default depend on the method name itself. If you want to change the way url should be constructed, you can include url_path as a decorator keyword argument.
Understanding ViewSet Classes
ViewSet
The base ViewSet class. Provides no actions by default. You define the actions yourself.
GenericViewSet
Extends GenericAPIView and ViewSetMixin. Provides
get_object, get_queryset methods but no actions.ReadOnlyModelViewSet
Provides
list and retrieve actions. Ideal for read-only APIs.ModelViewSet
Provides
list, create, retrieve, update, partial_update, and destroy actions.Binding ViewSets to URLs explicitly
The handler methods only get bound to the actions when we define the URLConf. To see what’s going on under the hood let’s first explicitly create a set of views from our ViewSets. In thesnippets/urls.py file we bind our ViewSet classes into a set of concrete views.
snippets/urls.py
ViewSet class, by binding the HTTP methods to the required action for each view.
Now that we’ve bound our resources into concrete views, we can register the views with the URL conf as usual.
snippets/urls.py
ViewSet Action Mapping
List Action
List Action
Maps to
GET /resources/ - Returns a list of all instances.Create Action
Create Action
Maps to
POST /resources/ - Creates a new instance.Retrieve Action
Retrieve Action
Maps to
GET /resources/{id}/ - Retrieves a single instance.Update Actions
Update Actions
Maps to
PUT /resources/{id}/ or PATCH /resources/{id}/ - Updates an instance.Destroy Action
Destroy Action
Maps to
DELETE /resources/{id}/ - Deletes an instance.Using Routers
Because we’re usingViewSet classes rather than View classes, we actually don’t need to design the URL conf ourselves. The conventions for wiring up resources into views and urls can be handled automatically, using a Router class. All we need to do is register the appropriate view sets with a router, and let it do the rest.
Here’s our re-wired snippets/urls.py file.
snippets/urls.py
DefaultRouter class we’re using also automatically creates the API root view for us, so we can now delete the api_root function from our views module.
Router Features
Automatic root view
DefaultRouter includes a default root view that returns a response containing hyperlinks to all the list views.Custom actions support
Routers automatically include URLs for custom actions defined with the
@action decorator.Available Routers
SimpleRouter
Includes routes for the standard set of
list, create, retrieve, update, partial_update and destroy actions.DefaultRouter
Similar to SimpleRouter, but additionally includes a default API root view that returns a response containing hyperlinks to all the list views.
Trade-offs between views vs ViewSets
Using ViewSets can be a really useful abstraction. It helps ensure that URL conventions will be consistent across your API, minimizes the amount of code you need to write, and allows you to concentrate on the interactions and representations your API provides rather than the specifics of the URL conf. That doesn’t mean it’s always the right approach to take. There’s a similar set of trade-offs to consider as when using class-based views instead of function-based views. Using ViewSets is less explicit than building your API views individually.When to Use ViewSets
Standard CRUD Operations
When your API follows standard create, read, update, delete patterns.
Multiple Related Endpoints
When you have list and detail views for the same model.
Consistent URL Structure
When you want to maintain consistent URL patterns across your API.
Rapid Development
When you want to reduce boilerplate and develop quickly.
When to Use Regular Views
Custom Behavior
When your endpoints don’t map well to standard CRUD operations.
One-off Endpoints
When you have standalone endpoints that don’t fit a ViewSet pattern.
Complex Logic
When you need fine-grained control over each endpoint’s behavior.
Explicit is Better
When you prefer explicit URL configuration for clarity.
Summary
Congratulations! You’ve completed the Django REST Framework tutorial series. We’ve covered:Requests & Responses
Using REST framework’s Request and Response objects for flexible content negotiation.
Authentication & Permissions
Adding authentication and fine-grained permissions to control API access.
Relationships & Hyperlinks
Creating hyperlinked APIs for better discoverability and following REST principles.
For more information, check out the API Guide for detailed documentation on all of REST framework’s features.
