如何在Django视图中显示PDF文件?

SIm*_*mon 28 python pdf django model-view-controller

是否可以 Django视图中显示PDF文件,而不是让用户下载它来查看它?

如果有可能,它会怎么做?

这是我到目前为止 -

@login_required
def resume(request, applicant_id):

    #Get the applicant's resume
    resume = File.objects.get(applicant=applicant_id)
    fsock = open(resume.location, 'r')
    response = HttpResponse(fsock, mimetype='application/pdf')

    return response
Run Code Online (Sandbox Code Playgroud)

Chr*_*att 32

简单地说,如果您有一个PDF文件并且想要通过Django视图输出它,那么您需要做的就是将文件内容转储到响应中并使用适当的mimetype发送它.

def pdf_view(request):
    with open('/path/to/my/file.pdf', 'r') as pdf:
        response = HttpResponse(pdf.read(), mimetype='application/pdf')
        response['Content-Disposition'] = 'inline;filename=some_file.pdf'
        return response
    pdf.closed
Run Code Online (Sandbox Code Playgroud)

您可以直接返回响应而不指定Content-Disposition,但这更好地表明了您的意图,并且允许您指定文件名以防用户决定保存它.

另请注意,上面的视图无法处理无论出于何种原因无法打开或读取文件的情况.由于它已经完成with,它不会引发任何异常,但您仍然必须返回某种响应.不过,你可以简单地提出一个Http404或者什么.

  • content_type,pdf.closed也没有效果 (4认同)
  • 它对我不起作用,直到我将 `mimetype='application/pdf` 更改为 `contenttype='application/pdf'` (2认同)
  • @azuax 它在上下文处理器中,返回没有`__exit__` 调用吗? (2认同)

Fli*_*imm 30

Django有一个专门用于返回文件的类FileResponse.它会传输文件,因此您无需在返回之前将整个文件读入内存.干得好:

from django.http import FileResponse, Http404

def pdf_view(request):
    try:
        return FileResponse(open('foobar.pdf', 'rb'), content_type='application/pdf')
    except FileNotFoundError:
        raise Http404()
Run Code Online (Sandbox Code Playgroud)

如果您有非常大的文件或者您正在做这么多,那么更好的选择可能是使用普通服务器配置在Django之外提供这些文件.


MKM*_*MKM 9

如果您在Windows机器PDF工作必须打开的rb不是r.

def pdf_view(request):
    with open('/path / to /name.pdf', 'rb') as pdf:
        response = HttpResponse(pdf.read(),content_type='application/pdf')
        response['Content-Disposition'] = 'filename=some_file.pdf'
        return response
Run Code Online (Sandbox Code Playgroud)


小智 6

取出内联; 如果您希望从服务器读取您的文件.此外,HttpResponsekwarg mimetype已被替换为content_type:

(response['Content-Disposition'] = 'inline;filename=some_file.pdf')

def pdf_view(request):
    with open('/app/../Test.pdf', 'r') as pdf:
        response = HttpResponse(pdf.read(),content_type='application/pdf')
        response['Content-Disposition'] = 'filename=some_file.pdf'
        return response
    pdf.closed
Run Code Online (Sandbox Code Playgroud)


chi*_*imo 6

按照上面@radtek 的回答,我决定研究基于类的视图显示。我尝试使用View但它没有get_context_data()方法。

在这里寻找一些指导。我选择了,BaseDetailView因为我只想显示一个对象。

from django.http import FileResponse
from django.shortcuts import get_object_or_404
from django.views.generic.detail import BaseDetailView

class DisplayPdfView(BaseDetailView):
    def get(self, request, *args, **kwargs):
        objkey = self.kwargs.get('pk', None) #1
        pdf = get_object_or_404(Pdf, pk=objkey) #2
        fname = pdf.filename() #3
        path = os.path.join(settings.MEDIA_ROOT, 'docs\\' + fname)#4
        response = FileResponse(open(path, 'rb'), content_type="application/pdf")
        response["Content-Disposition"] = "filename={}".format(fname)
        return response
Run Code Online (Sandbox Code Playgroud)

评论

1 此行访问pk调用视图的 url 传递的命名参数。

2 此行获取实际的 pdf 模型对象。

3 我filename(self): return os.path.basename(self.file.name)在我的模型中定义了一个方法来帮助我获得文件名和扩展名。

4 此行获取完整的文件路径。

然后使用上面答案中所述的文件响应。还记得使用rb阅读pdf文件