[Django]-Uploading base64 images using ModelSerializers in Django/django-rest-framework

6👍

The Corresponding Serializer would be as follows:

from rest_framework import serializers
from .models import Profile     

class Base64ImageField(serializers.ImageField):

    def to_internal_value(self, data):
        from django.core.files.base import ContentFile
        import base64
        import six
        import uuid

        if isinstance(data, six.string_types):
            if 'data:' in data and ';base64,' in data:
                header, data = data.split(';base64,')

            try:
                decoded_file = base64.b64decode(data)
            except TypeError:
                self.fail('invalid_image')

            file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
            file_extension = self.get_file_extension(file_name, decoded_file)
            complete_file_name = "%s.%s" % (file_name, file_extension, )
            data = ContentFile(decoded_file, name=complete_file_name)

        return super(Base64ImageField, self).to_internal_value(data)

    def get_file_extension(self, file_name, decoded_file):
        import imghdr

        extension = imghdr.what(file_name, decoded_file)
        extension = "jpg" if extension == "jpeg" else extension

        return extension

class PhotoSerializer(serializers.ModelSerializer):
    profile_picture = Base64ImageField(max_length=None, use_url=True)

    class Meta:
       model = Profile
       fields = ('profile_picture',)

1👍

Are you specifying content-type for your upload? ‘multipart/form-data’ ? You may need to specify the MultiPartParser on your view to accept file uploads.

from rest_framework.parsers import JSONParser, MultiPartParser

class ProfileViewSet(viewsets.ModelViewSet):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializers
    parser_classes = (MultiPartParser, JSONParser)

In serializers.py

import base64

from django.core.files.base import ContentFile
from rest_framework import serializers

# From  gist.github.com/yprez/7704036
class Base64ImageField(serializers.ImageField):
    def from_native(self, data):
        if isinstance(data, basestring) and data.startswith('data:image'):
            # base64 encoded image - decode
            format, imgstr = data.split(';base64,')  # format ~= data:image/X,
            ext = format.split('/')[-1]  # guess file extension

            data = ContentFile(base64.b64decode(imgstr), name='temp.' + ext)

        return super(Base64ImageField, self).from_native(data)


class ProfileSerializer(serializers.ModelSerializer):
    profile_picture =  Base64ImageField()

    class Meta:
        model = Profile
        fields = ('profile_picture',)

Leave a comment