Skip to main content

Welcome to a Grasp lesson

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

Lesson 42

DRF Generic Views & Mixins: Reducing Boilerplate

Recommended resources

Hello! Welcome back to your Django REST Framework journey.

In our last lesson, we transitioned from function-based views to class-based views using APIView. You saw how APIView provides a clean, object-oriented way to organize logic for different HTTP methods. However, you probably also noticed that implementing standard CRUD (Create, Retrieve, Update, Delete) operations with APIView involves writing a lot of similar, boilerplate code.

Today, we'll tackle that exact problem. This lesson is all about the DRY principle—Don't Repeat Yourself. Your learning outcome is to describe the role of DRF's generic views and mixins in reducing boilerplate code. We will explore how DRF provides a powerful set of tools that allow you to build robust, feature-complete API endpoints with just a few lines of code. This directly addresses your goal of learning to build REST APIs efficiently while also satisfying your curiosity about the framework's internal workings.

The Boilerplate Problem with APIView

Before we see the solution, let's firmly establish the problem. Implementing a full set of CRUD endpoints for a single model using APIView is verbose. You end up writing code to:

  • Query the database for all objects (for a list view).
  • Query the database for a single object (for a detail view).
  • Instantiate the serializer.
  • Check if the serializer is valid.
  • Save the data.
  • Return the appropriate success or error response.

This pattern repeats for almost every model in your application. The following video demonstrates exactly how much code this can be.

Class Based Views. (Generic API Views And Model Mixins) | Learn Django REST Framework #5

This video from Ssali Jonathan builds out a full set of CRUD views using the APIView class we learned about previously. You don't need to code along, just watch and pay close attention to the repetitive patterns in the code.

Watch from 00:40 to 08:20 to see the implementation of the list and create view. Then, watch from 10:03 to 18:56 to see the implementation of the retrieve, update, and delete view. Notice how similar the logic is for fetching objects, handling serializers, and returning responses in each method.

As you saw, the logic is very similar across different views. This is where DRF's generic views come to the rescue.


A Hierarchy of Abstraction

DRF's solution is not a single magic class, but a compositional system built on layers of abstraction. This approach allows you to choose the right level of control versus convenience for your needs.

There are three key components you need to understand:

  1. GenericAPIView: The base class that provides the core, shared functionality, like accessing the model's queryset and the serializer_class. It doesn't handle any HTTP methods on its own.
  2. Mixins: Small classes that provide specific actions, such as CreateModelMixin (which provides a .create() method) or ListModelMixin (which provides a .list() method). Since you're proficient with Python classes, you can think of these as a practical application of multiple inheritance to "mix in" specific behaviors.
  3. Concrete Generic Views: Ready-to-use views that combine GenericAPIView with one or more mixins. For example, ListCreateAPIView is simply a pre-built combination of GenericAPIView, ListModelMixin, and CreateModelMixin.

This flowchart provides an excellent visual representation of how these pieces fit together.

Django REST Framework Generic Views and Mixins Flowchart
This flowchart shows how the base `GenericAPIView` is combined with various `Mixin` classes (like `ListModelMixin`, `CreateModelMixin`) to create the final `Concrete View Classes` (like `ListCreateAPIView`). It clearly illustrates the compositional nature of DRF's generic views.

To get a formal definition of these components, take a few minutes to read the following sections.

All About Views in Django REST Framework(DRF) ...

This article from Python in Plain English provides clear, concise definitions for GenericAPIView, Mixins, and Concrete Views.

Read the sections 'Generic Views — Overview', 'GenericAPIView', 'Mixins', and 'Concrete Views'. Focus on understanding the distinct role each component plays in the system.


The Building Blocks: GenericAPIView and Mixins

Let's now see how these components drastically reduce the code we saw earlier. We'll start by manually combining GenericAPIView with the necessary mixins. This intermediate step is crucial for understanding how the final "magic" of concrete views works.

Class Based Views. (Generic API Views And Model Mixins) | Learn Django REST Framework #5

Continuing with the same video, watch how the author refactors the verbose APIView classes into much leaner versions using GenericAPIView and mixins.

Watch from 20:42 to 32:48. Observe how: The view class now inherits from GenericAPIView and several Mixin classes. The queryset and serializer_class are defined as class attributes. The get, post, put, and delete methods are reduced to a single line that calls the corresponding method from the mixin (e.g., return self.list(...)).

The code is significantly shorter! All the repetitive logic for querying, serializing, and validating has been abstracted away into the mixins.


Under the Hood: How Do the Mixins Work?

Your desire to understand the theory is key here. What is actually happening inside self.create() or self.list()? These methods aren't magic; they contain the same logic you would have written manually in an APIView.

The next video gives an exceptional look into the internal workings of these mixin methods. It uses a tool called "Classy Django REST Framework" to inspect the source code.

Django REST Framework - Creating Data | ListCreateAPIView and Generic View Internals

This video from BugBytes provides a deep dive into the internals of the mixin classes, explaining exactly what they do.

Watch from 07:15 to 14:49. The presenter explains what ListCreateAPIView is, and then uses a website to explore the source code of the .list() and .create() methods provided by the mixins. This will show you the exact boilerplate code that DRF is handling on your behalf.

This peek "under the hood" should make it clear that generic views aren't doing anything mysterious. They are simply providing a well-tested, reusable implementation of the patterns you were writing yourself.


The Sweet Spot: Concrete Generic Views

While manually combining GenericAPIView and mixins is a great learning exercise, DRF provides an even simpler way: Concrete Generic Views. These are the pre-built classes like ListAPIView, CreateAPIView, and ListCreateAPIView.

This is the level of abstraction you will work with most of the time.

Django REST Framework API View Hierarchy
This diagram shows the hierarchy of DRF views. Note how `GenericAPIView` and `Mixins` combine to form `Concrete APIView` classes. The arrow on the right indicates that as you use higher-level abstractions like Concrete Views and ViewSets, the ease of use increases.

The following article explains why these concrete views are the "sweet spot" for most API development.

Choosing Between FBVs, APIView, Generics, and ViewSets

This article from dev.to gives a fantastic, practical guide on when to use each type of view and makes a strong case for using Concrete Generic Views as your default choice.

Read 'Level 3: GenericAPIView + Mixins' and 'Level 4: Concrete Generic Views'. Compare the code for ProductList in both sections. You'll see that the Concrete View (ListCreateAPIView) eliminates the need to even define the get() and post() methods, as it's handled by default.

Using a concrete view like generics.ListCreateAPIView, the entire view for listing and creating posts is reduced to just three lines of code:

from rest_framework import generics
from .models import Post
from .serializers import PostSerializer

class PostListCreateView(generics.ListCreateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

This is the power of generic views. All the functionality from the 100+ lines of APIView code we saw at the start is now handled by this simple, declarative class.

Test your understanding!

Imagine you have written the following view using APIView to handle retrieving and deleting a single Comment object.

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404

class CommentDetailView(APIView):
    """
    Retrieve or delete a comment instance.
    """
    def get_object(self, pk):
        try:
            return Comment.objects.get(pk=pk)
        except Comment.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        comment = self.get_object(pk)
        serializer = CommentSerializer(comment)
        return Response(serializer.data)

    def delete(self, request, pk, format=None):
        comment = self.get_object(pk)
        comment.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Which single Concrete Generic View would you use to replace this entire class, and what would the new, much shorter code look like?

Show answer

You would use generics.RetrieveDestroyAPIView.

This single class provides both the GET (retrieve) and DELETE (destroy) functionality out of the box. The new code would be:

from rest_framework import generics
from .models import Comment
from .serializers import CommentSerializer

class CommentDetailView(generics.RetrieveDestroyAPIView):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer

That's it! DRF handles the object lookup (based on the pk in the URL), serialization, and response generation for both GET and DELETE requests automatically.


Conclusion

Today you've seen how Django REST Framework provides a layered system of abstractions to eliminate boilerplate code for common API patterns. This not only speeds up development but also leads to more robust and maintainable code.

Key Takeaways:

  • APIView is powerful for custom logic but leads to repetitive code for standard CRUD operations.
  • GenericAPIView provides the foundational behavior (linking a queryset and serializer_class) for views that map to models.
  • Mixins (ListModelMixin, CreateModelMixin, etc.) provide specific actions like .list() and .create(). They encapsulate the reusable logic.
  • Concrete Generic Views (ListCreateAPIView, RetrieveUpdateDestroyAPIView, etc.) are the most convenient layer, combining GenericAPIView and mixins into ready-to-use classes that you'll use for most of your endpoints.

Preview of the Next Lesson:
We've covered the theory and seen the code. In the next lesson, we will put this knowledge into practice. You will implement a list/create endpoint using ListCreateAPIView and a detail/update/delete endpoint using RetrieveUpdateDestroyAPIView in our project, solidifying your understanding and experiencing the productivity gains firsthand.