[Django]-Django REST Framework + Django REST Swagger + ImageField

6👍

This is the final solution I came up with:

from rest_framework import generics
from rest_framework.parsers import FormParser, MultiPartParser
from .serializer import MyModelSerializer

class MyModelView(generics.CreateAPIView):
    serializer_class = MyModelSerializer
    parser_classes = (FormParser, MultiPartParser)

    def post(self, *args, **kwargs):
        """
            Create a MyModel
            ---
            parameters:
                - name: source
                  description: file
                  required: True
                  type: file
            responseMessages:
                - code: 201
                  message: Created
        """
        return super(MyModelView, self).post(self, *args, **kwargs)

All I had to do was change the parsers from FileUploadParser to (FormParser, MultiPartParser)

8👍

I got this working by making a couple of changes to your code.

First, in models.py, change ImageField name to file and use relative path to upload folder. When you upload file as binary stream, it’s available in request.data dictionary under file key (request.data.get('file')), so the cleanest option is to map it to the model field with the same name.

from django.utils import timezone
from django.db import models


class MyModel(models.Model):

    file = models.ImageField(upload_to=u'photos')
    is_active = models.BooleanField(default=False)
    created_at = models.DateTimeField(default=timezone.now)

    def __unicode__(self):
        return u"photo {0}".format(self.file.url)

In serializer.py, rename source field to file:

class MyModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyModel
        fields = ('id', 'file', 'created_at')

In views.py, don’t call super, but call create():

from rest_framework import generics
from rest_framework.parsers import FileUploadParser

from .serializer import MyModelSerializer


class MyModelView(generics.CreateAPIView):
    serializer_class = MyModelSerializer
    parser_classes = (FileUploadParser,)

    def post(self, request, *args, **kwargs):
        """
            Create a MyModel
            ---
            parameters:
                - name: file
                  description: file
                  required: True
                  type: file
            responseMessages:
                - code: 201
                  message: Created
        """
        return self.create(request, *args, **kwargs)

I’ve used Postman Chrome extension to test this. I’ve uploaded images as binaries and I’ve manually set two headers:

Content-Disposition: attachment; filename=upload.jpg
Content-Type: */*

3👍

It has been my experience that the FileUploadParser works with this format of a request:

    curl -X POST -H "Content-Type:multipart/form-data" \
                 -F "file=@{filename};type=image/jpg" \
                 https://endpoint.com/upload-uri/

The request.data['file'] in your view will have the file.

Maybe if you try a Content-Type:multipart/form-data header, you will have luck.

Leave a comment