Bulk Create With Django REST Framework
Monday November 27 2017

In this quick post I will go over how to create an endpoint that allows bulk creation of a resource using Django REST Framework.

The Serializer

Let's assume that we will be working with an existing Book model in our Django application. We will create a serializer for this model using Django REST's ModelSerializer helper class:

# serializers.py
from models import Book
from rest_framework import serializers


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

The "__all__" string indicates that we want to serialize all of the model's fields.

The View

Before creating the view, we will first need to create a mixin that will allow the view to handle an array of JSON objects in the request so that the actual view can process and create new objects in a bulk fashion:

# views.py


class CreateListBookMixin:
    """Allows bulk creation of books."""
    def get_serializer(self, *args, **kwargs):
        if isinstance(kwargs.get('data', {}), list):
            kwargs['many'] = True

        return super().get_serializer(*args, **kwargs)

This mixin overwrites the get_serializer method and makes it check if the incoming body is a list. If it is, it proceeds to assign a boolean value for the many key in the kwargs.

Adding the CreateList prefix to the mixin class name is a good naming practice that quickly allows us to know that this is a mixin for bulk creation.

We can now create this view and make it use the mixin. We will make use of Django REST's ModelViewSet to simplyify things:

from serializers import BoookSerializer
from models import Book

from rest_framework import viewsets


class BookViewSet(CreateListBookMixin, viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

Setting the URL

Lastly we need to set a URL to make the request to. We can use a Django REST router to easily set this endpoint up:

# urls.py
from django.conf.urls import url, include
from views import BookViewSet
from rest_framework import routers


router = routers.DefaultRouter()
router.register(r'books', BookViewSet)


python django

Comments

comments powered by Disqus