Base64 images with django rest framework
174
Introduction
Base64 encoding is a technique to convert binary data into an ASCII string format. When dealing with APIs, Base64 is useful for transmitting image data in JSON payloads, making it easier to handle image uploads without requiring multipart form data. Django Rest Framework (DRF) is a powerful toolkit for building Web APIs in Django, and it provides the flexibility needed to handle Base64 images.
This tutorial will cover:
- Setting up a Django project and app.
- Creating a model to store image data.
- Writing a serializer to handle Base64 image input.
- Updating views to process the image data.
- Testing the image upload functionality.
Steps
Step 1: Setting Up the Django Project
First, create a new Django project and app. Install Django and DRF if you haven't already.
pip install django djangorestframework
django-admin startproject myproject
cd myproject
python3 manage.py startapp myapp
Add rest_framework
and your app to the INSTALLED_APPS
in settings.py
.
# myproject/settings.py
INSTALLED_APPS = [ ... 'rest_framework', 'myapp', ]
Step 2: Creating the Model
Create a model to store the image data. In this example, we'll create a simple model with an ImageField
.
# myapp/models.py
from django.db import models
class ImageModel(models.Model):
image = models.ImageField(upload_to='images/')
python manage.py makemigrations
python manage.py migrate
Step 3: Writing the Serializer
Create a serializer to handle the Base64 encoded image. We'll use a custom field to handle the Base64 decoding.
from django.core.files.uploadedfile import InMemoryUploadedFile
from .models import ImageModel
class ImageByteField(serializers.Field):
def to_internal_value(self, data):# Assuming data is already bytes
return data
def to_representation(self, value):
# Encode bytes to base64 for representation
return base64.b64encode(value).decode('utf-8')
class ImageSerializer(serializers.ModelSerializer):
image = ImageByteField(required=False)
class Meta:
model = ImageModel
fields = ('id', 'image')
def create(self, data):
serialized_image = data.get('image')
#convert base 64 bytes to image file
image = InMemoryUploadedFile(
serialized_image,
None,
'image.jpg', # Or dynamically determine the name and extension
'image/jpeg', # Or dynamically determine the content type
None,# Add the file size
None) # Charset is optional, so pass None
return ImageModel.objects.create(image=image)
Step 4: Updating the Views
# myapp/views.py
from rest_framework.status import (
HTTP_400_BAD_REQUEST,
HTTP_201_CREATED,
)
from rest_framework import generics
from .serializer import ImageSerializer
from rest_framework.response import Response
class ImageCreateAPIView(generics.CreateAPIView):
serializer_class = ImageSerializer
def post(self, request, format=None):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
data = serializer.save()
data = {'image': data.image.url}
return Response(data, status=HTTP_201_CREATED)
else:
data = {"message": serializer.errors}
return Response(data, status=HTTP_400_BAD_REQUEST)
Configure the URLs to include the new viewset.
# myproject/urls.py from django.contrib import admin from django.urls import path from myapp.views import ImageCreateAPIView urlpatterns = [ path('admin/', admin.site.urls), path('api/images/', ImageCreateAPIView.as_view(), name='image-create'), ]
Step 5: Testing the Image Upload
With the setup complete, you can now test the image upload functionality. Use a tool like Postman to send a POST request to the /api/images/
endpoint with a JSON payload containing the Base64 encoded image data.
Example JSON payload:
{ "image": "/9j/4AAQSkZJRgABAQAAAQABAAD..." }
Conclusion
Handling Base64 images in Django Rest Framework is a straightforward process. By creating a custom serializer field, you can seamlessly decode Base64 image data and save it to your models. This approach simplifies image handling in APIs, making it easier to work with JSON payloads without the need for multipart form data. With this guide, you should be able to implement Base64 image uploads in your own Django projects efficiently.