title: What is the best design pattern for batch insertion using the Django REST Framework?
body: <h3>Background</h3>
  
  <p>I have a Django app that allows record insertion via the Django REST Framework.</p>
  
  <p>Records will be periodically batch-inserted row-by-row by client applications that interrogate spreadsheets and other databases. The REST API allows these other applications, which handle data transformation, etc, to be abstracted from Django.</p>
  
  <h3>Problem</h3>
  
  <p>I'd like to decouple the actual record insertion from the API to improve fault tolerance and the potential for scalability.</p>
  
  <h3>Suggested Approach</h3>
  
  <p>I am considering doing this with Celery, but I've not used it before. I'm considering overriding <code>perform_create()</code> in my existing DRF ModelViewSets (<code>perform_create()</code> was added in <a href="http://www.django-rest-framework.org/topics/3.0-announcement/#generic-views" rel="noreferrer">DRF 3.0</a>) to create Celery tasks that workers would grab and process in the background.</p>
  
  <p>The DRF documentation says that <code>perform_create()</code> should "should save the object instance by calling serializer.save()". I'm wondering whether, in my case, I could ignore this recommendation and instead have my Celery tasks call on the appropriate serializer to perform the object saves.</p>
  
  <h3>Example</h3>
  
  <p>If for example I've got a couple of models:</p>
  
  <pre><code>class Book(models.Model):
      name = models.CharField(max_length=32)
  
  class Author(models.Model):
      surname = models.CharField(max_length=32)
  </code></pre>
  
  <p>And I've got DRF views and serializers for those models:</p>
  
  <pre><code>class BookSerializer(serializers.ModelSerializer):
      class Meta:
          model = Book
  
  class AuthorSerializer(serializers.ModelSerializer):
      class Meta:
          model = Author
  
  class BookViewSet(viewsets.ModelViewSet):
      queryset = Book.objects.all()
      serializer_class = Book
  
  class AuthorViewSet(viewsets.ModelViewSet):
      queryset = Author.objects.all()
      serializer_class = Author
  </code></pre>
  
  <p>Would it be a good idea to override perform_create() in e.g. <code>BookViewSet</code>:</p>
  
  <pre><code>def perform_create(self, serializer):
      create_book_task(serializer.data)
  </code></pre>
  
  <p>Where <code>create_book_task</code> is separately something like:</p>
  
  <pre><code>@shared_task
  def create_book_task(data):
      serializer = BookSerializer(data=data)
      serializer.save()
  </code></pre>
  
  <p>I've not really been able to find any examples of other developers doing something similar or trying to solve the same problem. Am I overcomplicating it? My database is still going to be the limiting factor when it comes to physical insertion, but at least it won't block the API clients from queueing up their data. I am not committed to Celery if it isn't suitable. Is this the best solution, are there obvious problems with it, or are there better alternatives?</p>