首页 文章

如何使用Django REST Framework返回生成的文件下载?

提问于
浏览
8

我需要将生成的文件下载作为Django REST Framework响应返回 . 我尝试了以下方法:

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

但它返回一个msword文档为 json .

如何让它开始作为文件下载?

3 回答

  • 4

    以下是直接从DRF返回文件下载的示例 . 诀窍是使用自定义渲染器,以便您可以直接从视图返回响应:

    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
    

    注意我使用自定义 endpoints download 而不是默认 endpoints retrieve ,因为这样可以轻松地为此 endpoints 而不是整个视图覆盖渲染器 - 并且它往往对列表和细节有意义返回常规无论如何JSON . 如果要选择性地返回文件下载,可以向自定义渲染器添加更多逻辑 .

  • 1

    我通过将文件保存在媒体文件夹中并将其链接发送到前端来解决了我的问题 .

    @permission_classes((permissions.IsAdminUser,))
    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(serializer.data)
            document = template.render(Context(context))
            doc = converter().convert(document, format='doc')
            p = u'docs/cards/%s/%s_%s.doc' % (datetime.now().date(), context[u'surname'], context[u'name'])
            path = default_storage.save(p, doc)
            return response.Response(u'/media/' + path)
    

    并在我的前端处理这个(AngularJS SPA)

    $http(req).success(function (url) {
        console.log(url);
        window.location = url;
    })
    
  • 1

    这可能对你有用:

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

    对于FrontEnd代码,请参阅this

相关问题