Mixins
Mixins provide basic view behavior without directly defining HTTP methods like get() or post(). They contain the core logic for interacting with your models and serializers, such as returning a list of objects or creating a new object.
By themselves, mixin classes have no utility. They must be combined with a base class, specifically GenericAPIView (discussed later). This base class provides the necessary foundation like the queryset and serializer_class.
The Mixin Classes
There are five core mixins, each mapping to a standard CRUD operation.
ListModelMixin
Provides a .list(request, *args, **kwargs) method that fetches a queryset, applies pagination if configured, serializes the data, and returns a 200 OK response.
CreateModelMixin
Provides a .create(request, *args, **kwargs) method that validates request data, saves a new model instance, and returns a 201 Created response. If validation fails, it returns a 400 Bad Request.
It also provides a .perform_create(serializer) hook that you can override to inject additional logic before saving (e.g., setting the author of a blog post to the current user).
NOTE
A "hook" is simply a dedicated method provided by the mixin that is designed to be overridden by your subclass to customize specific behavior without having to rewrite the entire core method.
RetrieveModelMixin
Provides a .retrieve(request, *args, **kwargs) method that fetches a single model instance based on the URL parameter (usually pk), serializes it, and returns a 200 OK response.
UpdateModelMixin
Provides an .update(request, *args, **kwargs) method that updates an existing instance and returns a 200 OK.
It also supports partial updates (HTTP PATCH) via the .partial_update(request, *args, **kwargs) method. Similar to create, it offers a .perform_update(serializer) hook.
DestroyModelMixin
Provides a .destroy(request, *args, **kwargs) method that deletes a model instance and returns a 204 No Content response. It includes a .perform_destroy(instance) hook for custom deletion logic.
Using Mixins
To use mixins, you must inherit from your chosen mixin classes as well as a base class like GenericAPIView. You then bind standard HTTP methods to the mixin actions.
from rest_framework import generics, mixins
from .models import Blog
from .serializers import BlogSerializer
class BlogList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
# GenericAPIView requires these
queryset = Blog.objects.all()
serializer_class = BlogSerializer
# Bind GET to the ListModelMixin's .list()
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
# Bind POST to the CreateModelMixin's .create()
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)GenericAPIView will be covered shortly in the next page, but what you need to observe in this example is how we explicitly map the HTTP verbs to the mixin methods. By wiring get() to list() and post() to create(), you create a fully functional Collection API with minimal code.
Custom Mixins
You can also create your own custom mixins to share reusable behavior across multiple views. A common use case is replacing default DRF behavior with your own logic.
For example, you might want a SoftDeleteModelMixin that you can use instead of DRF's default DestroyModelMixin to flag records as deleted rather than permanently removing them from the database:
from rest_framework import status
from rest_framework.response import Response
class SoftDeleteModelMixin:
"""
Deletes a model instance by setting an `is_active` flag to False,
rather than actually removing it from the database.
"""
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.is_active = False
instance.save()By creating this custom mixin, you can simply drop SoftDeleteModelMixin into any of your views in place of DestroyModelMixin to instantly apply this behavior.
