How to Upload Files using DRF

How do you upload images using Django REST Framework? Could you imagine if it was similar to using regular everyday Django?

Follow this mini tutorial and you’ll find out! :)

If you want to follow along, I have a git repository you can find here.


Want to get started learning Django REST Framework? Sign up for a FREE 7 Day Email Course today. Click here for more information


The first thing you should do is set your MEDIA_URL and MEDIA_ROOT variables. For the sake of this example, I’m just going to use /media/ as both the URL and the ROOT directories.

settings.py

1
2
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

Now, in our app, I just create a simple FileField. But, if you just want to allow uploading Images, you would using ImageField.

Let’s look at my models.py.

models.py

1
2
3
4
5
6
from django.db import models

class MyFile(models.Model):
  	file = models.FileField(blank=False, null=False)
    description = models.CharField(max_lenth=255)
    uploaded_at = models.DateTimeField(auto_now_add=True)

The Serializer we are going to use is pretty simple:

serializers.py

1
2
3
4
5
6
7
from rest_framework import serializers
from .models import MyFile

class MyFileSerializer(serializers.ModelSerializer):
  	class Meta():
      	model = MyFile
        fields = ('file', 'description', 'uploaded_at')

And finally, we will need a View that can parse a multipart and a form so we can fully support any kind of HTML form data.

views.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework import status
from .serializers import MyFileSerializer

class MyFileView(APIView):
		# MultiPartParser AND FormParser
		# https://www.django-rest-framework.org/api-guide/parsers/#multipartparser
		# "You will typically want to use both FormParser and MultiPartParser
		# together in order to fully support HTML form data."
		parser_classes = (MultiPartParser, FormParser)
		def post(self, request, *args, **kwargs):
				file_serializer = MyFileSerializer(data=request.data)
				if file_serializer.is_valid():
						file_serializer.save()
						return Response(file_serializer.data, status=status.HTTP_201_CREATED)
				else:
						return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

We use the class-based View attribute for parser_classes to allow the View to parse both MultiPart and Form data.

Then, the url we use looks like this:

app/urls.py

1
2
3
4
5
6
from django.conf.urls import url
from .views import MyFileView

urlpatterns = [
  	url(r'^upload/$', MyFileView.as_view(), name='file-upload'),
]

We are finished! Let’s give it a go!


I use Postman to test REST APIs. So, let’s check it out. First download Postman here.

Next, let’s run our application.

1
2
3
4
$ pipenv sync
$ pipenv shell
$ cd drfuploads/
$ python manage.py runserver
  1. Now, let’s open up Postman.
  2. In the address bar type in: http://localhost:8000/file/upload/.
  3. Then, in the request method dropdown, select POST.

Now, click Send and you should see the following JSON:

1
2
3
4
5
6
7
8
{
  	"file": [
      	"No file was submittted."
    ],
  	"description": [
      	"This field is required."
    ]
}

Bad Request

This means that we didn’t select a file to upload. Let’s do that now:

Click the Body tab and under Key there is a hidden dropdown called Text. Switch it to File.

Send File

Next, select the file that we want to upload. Then, type in description as a second key-value pair and type in a description.

Send File 2

Now, click Send:

You should get the following JSON:

1
2
3
4
5
{
    "file": "/media/dude_I2FPPum.jpg",
    "description": "Big Lebowski",
    "uploaded_at": "2019-04-26T12:30:09.463345Z"
}

Send File Done

Congratulations! You just learned how to upload a File using Django REST Framework. And you learned how to test using Files using Postman.

You may use my code next time you need to allow files in Django REST Framework.


comments powered by Disqus