Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 27

Rapid API Development with DRF ViewSets & Routers

Recommended resources

In our previous lesson, you mastered the art of serialization, learning how to transform your Django Task model into JSON data using ModelSerializer. This was the essential first step toward building a web API. Now, we'll leverage that foundation to construct the API itself.

Our goal today is to build a complete set of CRUD (Create, Read, Update, Delete) endpoints for our Task model. While we could create separate views for each operation, Django REST Framework offers a much more powerful and efficient pattern. This lesson introduces ViewSets and Routers, a combination that allows you to build a fully-functional API with a surprisingly small amount of code. Mastering this directly addresses the core job requirement to "Design and develop REST APIs."

By the end of this lesson, you will be able to:

  • Explain how ViewSets consolidate logic for multiple related views.
  • Implement a ModelViewSet to provide a full set of CRUD actions for a model.
  • Use a DefaultRouter to automatically generate URL patterns for your ViewSet.
  • Test the complete set of generated API endpoints using DRF's browsable API.

1. The "ViewSet + Router" Pattern: A Paradigm Shift

In traditional Django development, you create distinct class-based views for different purposes: a ListView to show a list of objects, a DetailView for a single object, a CreateView to handle form posts, and so on. For an API, this would mean creating separate views to handle GET requests for lists, GET requests for details, POST requests for creation, PUT for updates, and DELETE for removal.

Django REST Framework streamlines this with ViewSets. A ViewSet is a single class that groups together the logic for a set of related actions (like list, create, retrieve, update, destroy). Instead of mapping HTTP methods (get, post) directly in your URL configuration, you map them to these actions.

Even better, a ModelViewSet does almost all the work for you. By simply pointing it at a model and a serializer, it automatically provides the complete implementation for all standard CRUD actions.

But how do you create URLs for these actions? This is where Routers come in. A router automatically inspects your ViewSet and generates the standard URL patterns for you. This combination of ViewSet and Router is the key to rapid API development in DRF.

The entire workflow can be visualized as a pipeline:

This flowchart illustrates the core concept of this lesson. We define our Models and Serializers (which you've already done), create a ViewSet from them, and then register that ViewSet with a Router to automatically generate all the necessary API endpoints.

2. Hands-On: From Views to ViewSets

Let's refactor our TaskMaster project to use this powerful pattern. We will replace the need for multiple API views with a single TaskViewSet.

First, open your tasks/views.py file. We'll be adding a new class that uses viewsets.ModelViewSet.




# tasks/views.py

from .models import Task
from .serializers import TaskSerializer




# We will need this for our new ViewSet
from rest_framework import viewsets




# ... your existing web views (TaskListView, TaskDetailView etc.) can remain for now ...




# Add this new class for our API
class TaskViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.
    """
    queryset = Task.objects.all()
    serializer_class = TaskSerializer

That's it. Notice how incredibly concise this is. By inheriting from ModelViewSet and specifying the queryset and serializer_class, you've given DRF everything it needs to handle all CRUD operations for the Task model.

The video below demonstrates this exact process. While the model and serializer names are different, the concept is identical.

Viewsets & Routers in Django REST Framework

This video from the BugBytes channel provides a clear, practical walkthrough of creating a ModelViewSet.

Watch the segment from where the presenter creates the OrderViewSet. Observe how they inherit from viewsets.ModelViewSet and define the queryset and serializer_class attributes, just as you have done.


3. Wiring It All Up with a Router

Now that we have our TaskViewSet, we need to generate the URLs for it. We'll do this in your main project's URL configuration. This approach keeps your API URLs neatly organized under a common prefix, like /api/.

First, let's create a dedicated urls.py file for your app's API endpoints. Create a new file: tasks/api_urls.py.

Inside this new tasks/api_urls.py file, set up the router:




# tasks/api_urls.py

from rest_framework.routers import DefaultRouter
from .views import TaskViewSet




# Create a router and register our viewset with it.
router = DefaultRouter()
router.register(r'tasks', TaskViewSet, basename='task')




# The API URLs are now determined automatically by the router.
urlpatterns = router.urls

Here's what this code does:

  • DefaultRouter: We instantiate DRF's default router, which provides a nice browsable API root page.
  • router.register(): This is the core step. We're telling the router:
    • "Create URLs under the prefix tasks."
    • "Use the TaskViewSet to handle requests to these URLs."
    • basename='task' is used to generate the URL names.

Finally, we need to tell your main project to include these new API URLs. Open myproject/urls.py and modify it:




# myproject/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),




    # Add this line to include your API urls
    path('api/', include('tasks.api_urls')),




    # Your existing web app URLs can remain
    path('', include('tasks.urls')),
]

By including tasks.api_urls under the api/ path, all our API endpoints will now be accessible at URLs like /api/tasks/.

The following video segment demonstrates this router configuration process.

Viewsets & Routers in Django REST Framework

Continuing with the BugBytes video, see how a router is configured to generate URLs for the ViewSet.

Watch from . The presenter does this in the main urls.py, but the logic is the same: import DefaultRouter, instantiate it, register the viewset, and append router.urls to your urlpatterns.


4. Exploring Your Auto-Generated API

With just a few lines of code, you have created a complete REST API for your Task model. Let's see it in action.

Start your development server:

python manage.py runserver

Now, open your browser and explore the following URLs:

  • API Root (http://127.0.0.1:8000/api/): The DefaultRouter provides this handy landing page, which lists all registered API endpoints. You should see an entry for "tasks".

  • List and Create (http://127.0.0.1:8000/api/tasks/):

    • This page corresponds to the list action. You'll see a JSON representation of all the tasks in your database.
    • If you scroll down, you'll find an HTML form. This corresponds to the create action. You can use it to create a new task directly from the browser. Try it!
  • Retrieve, Update, and Delete (http://127.0.0.1:8000/api/tasks/1/) (replace 1 with a valid task ID):

    • This page corresponds to the retrieve action, showing the JSON for a single task.
    • The page also provides actions for DELETE (deleting the object) and PUT/PATCH (updating the object using the form at the bottom).

You've just verified that ModelViewSet and DefaultRouter have automatically provided handlers for all the standard RESTful operations.

The GeeksForGeeks article below provides a complete example from model to router, reinforcing what you've just built. The final table clearly shows the mapping between HTTP methods, URL patterns, and the actions provided by the ViewSet.

ViewSets & Routers - Django REST framework

This article provides another complete example of using ViewSets and Routers, which will help solidify your understanding.

In the article, focus on the comprehensive section Bookstore API. Skim through the models.py, serializers.py, and views.py code to see how they fit together. Pay close attention to the Router URLs section and the final tables under HTTP Methods, which explicitly lists all the endpoints that the router generates automatically.


Conclusion

In this lesson, you made a significant leap in productivity. By replacing individual views with the ModelViewSet and DefaultRouter pattern, you've learned how to rapidly generate a full suite of CRUD API endpoints. This is a cornerstone of professional Django backend development.

Key Takeaways:

  • A ViewSet is a class that consolidates the logic for a set of related API actions (list, create, retrieve, etc.).
  • A ModelViewSet is a powerful subclass that provides a full, default implementation of CRUD actions for a specific Django model.
  • A Router (like DefaultRouter) automatically inspects a ViewSet and generates a complete set of RESTful URL patterns.
  • The combination of these two components dramatically reduces boilerplate code and enforces consistent API design.

In our next lesson, we will address a critical issue: security. Currently, your new API is wide open for anyone to use. We will learn how to implement token-based authentication to ensure that only authorized users can access and modify data through your API endpoints.