How to return generated file download with Django REST Framework?


I need to return generated file download as a Django REST Framework response. I tried the following:

def retrieve(self, request, *args, **kwargs):
    template = webodt.ODFTemplate('test.odt')
    queryset = Pupils.objects.get(id=kwargs['pk'])
    serializer = StudentSerializer(queryset)
    context = dict(
    document = template.render(Context(context))
    doc = converter().convert(document, format='doc')
    res = HttpResponse(
    res['Content-Disposition'] = u'attachment; filename=""' % (context[u'surname'], context[u'name'])
    return res

But it returns a msword document as json.

How do I make it start downloading as file instead?

Asked By: Viktor



This may work for you:

file_path = file_url
FilePointer = open(file_path,"r")
response = HttpResponse(FilePointer,content_type='application/msword')
response['Content-Disposition'] = 'attachment; filename=NameOfFile'

return response.

For FrontEnd code refer this

Answered By: Piyush S. Wanare

I solved my problem by saving file in media folder and sending of the link of it to front-end.

class StudentDocxViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    def retrieve(self, request, *args, **kwargs):
        template = webodt.ODFTemplate('test.odt')
        queryset = Pupils.objects.get(id=kwargs['pk'])
        serializer = StudentSerializer(queryset)
        context = dict(
        document = template.render(Context(context))
        doc = converter().convert(document, format='doc')
        p = u'docs/cards/%s/%s_%s.doc' % (, context[u'surname'], context[u'name'])
        path =, doc)
        return response.Response(u'/media/' + path)

And handled this like in my front-end (AngularJS SPA)

$http(req).success(function (url) {
    window.location = url;
Answered By: Viktor

Here’s an example of returning a file download directly from DRF. The trick is to use a custom renderer so you can return a Response directly from the view:

from django.http import FileResponse
from rest_framework import viewsets, renderers
from rest_framework.decorators import action

class PassthroughRenderer(renderers.BaseRenderer):
        Return data as-is. View should supply a Response.
    media_type = ''
    format = ''
    def render(self, data, accepted_media_type=None, renderer_context=None):
        return data

class ExampleViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Example.objects.all()

    @action(methods=['get'], detail=True, renderer_classes=(PassthroughRenderer,))
    def download(self, *args, **kwargs):
        instance = self.get_object()

        # get an open file handle (I'm just using a file attached to the model for this example):
        file_handle =

        # send file
        response = FileResponse(file_handle, content_type='whatever')
        response['Content-Length'] = instance.file.size
        response['Content-Disposition'] = 'attachment; filename="%s"' %

        return response

Note I’m using a custom endpoint download instead of the default endpoint retrieve, because that makes it easy to override the renderer just for this endpoint instead of for the whole viewset — and it tends to make sense for list and detail to return regular JSON anyway. If you wanted to selectively return a file download you could add more logic to the custom renderer.

Answered By: Jack Cushman

I am using DRF and i found a view code to download file, which would be like

from rest_framework import generics
from django.http import HttpResponse
from wsgiref.util import FileWrapper

class FileDownloadListAPIView(generics.ListAPIView):

    def get(self, request, id, format=None):
        queryset = Example.objects.get(id=id)
        file_handle = queryset.file.path
        document = open(file_handle, 'rb')
        response = HttpResponse(FileWrapper(document), content_type='application/msword')
        response['Content-Disposition'] = 'attachment; filename="%s"' %
        return response

and will be


I am using React.js in frontend and i get a response like

handleDownload(id, filename) {
    response => {
      response.blob().then(blob => {
      let url = window.URL.createObjectURL(blob);
      let a = document.createElement("a");
      a.href = url; = filename;;

and after i got successful in downloading a file which also opens correctly and i hope this gonna work. Thanks

Answered By: Muhammad Zohaib

For me, using Python 3.6, Django 3.0, and DRF 3.10, The problem came from using the wrong type of response. I needed to use a django.http.HttpResponse, as seen below:

from django.http import HttpResponse
with open('file.csv', 'r') as file:
    response = HttpResponse(file, content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename=file.csv'
    return response
Answered By: DDriggs00


class Attachment(models.Model):
    file = models.FileField(upload_to=attachment_directory_path, blank=True, null=True)

    def filename(self):


import mimetypes
from django.http import FileResponse

class AttachmentViewSet(ModelViewSet):

    @action(methods=['GET'], detail=True)
    def download(self, request, **kwargs):
        att = self.get_object()
        file_handle =

        mimetype, _ = mimetypes.guess_type(att.file.path)
        response = FileResponse(file_handle, content_type=mimetype)
        response['Content-Length'] = att.file.size
        response['Content-Disposition'] = "attachment; filename={}".format(att.filename)
        return response

and in frontend, I used axios for download files. api is axios client.

export function fileDownload(url, filename){
  return api.get(url, { responseType: 'blob' })
      const url = window.URL.createObjectURL(new Blob([]));
      const link = document.createElement('a');
      link.href = url;
      link.setAttribute('download', filename);

hope that it helps

Answered By: Joon Mo Park

Using django-downloadview this can be done like so:

from rest_framework.decorators import action
from django_downloadview import ObjectDownloadView

class DocumentViewSet(viewsets.ReadOnlyModelViewSet):

    def download(self, request, pk):
        return ObjectDownloadView.as_view(
            model=, # your model here
        )(request, pk=pk)

The viewset can then be registered via DRF routers.

Answered By: David Wolf