How to return generated file download with Django REST Framework?

后端 未结 5 1323
清歌不尽
清歌不尽 2021-02-04 03:20

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

def retrieve(self, request, *args, **kwargs):
    template =         


        
5条回答
  •  佛祖请我去吃肉
    2021-02-04 04:25

    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 = instance.file.open()
    
            # send file
            response = FileResponse(file_handle, content_type='whatever')
            response['Content-Length'] = instance.file.size
            response['Content-Disposition'] = 'attachment; filename="%s"' % instance.file.name
    
            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.

提交回复
热议问题