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

Python 如何在Django视图中显示PDF文件?,python,django,model-view-controller,pdf,Python,Django,Model View Controller,Pdf,是否可以在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') respon

是否可以在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

简单地说,如果您有一个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
您可以直接返回响应而不指定内容配置,但这样可以更好地表明您的意图,并允许您指定文件名,以防用户决定保存它


另外,请注意,上面的视图不处理由于任何原因无法打开或读取文件的情况。由于它是用
完成的,因此不会引发任何异常,但您仍然必须返回某种响应。不过,你可以简单地提出一个
Http404
之类的东西。

浏览器不是PDF阅读器(除非它们有合适的插件/插件)


您可能希望将PDF呈现为HTML,这可以通过内联方式完成或。

取出;如果您希望从服务器读取文件。而且,
HttpResponse
kwarg
mimetype
已被
content\u 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

以下是使用基于类的视图显示PDF的典型用例:

from django.contrib.auth.decorators import login_required
from django.http import HttpResponse

class DisplayPDFView(View):

    def get_context_data(self, **kwargs):  # Exec 1st
        context = {}
        # context logic here
        return context

    def get(self, request, *args, **kwargs):
        context = self.get_context_data()
        response = HttpResponse(content_type='application/pdf')
        response['Content-Disposition'] = 'inline; filename="worksheet_pdf.pdf"'  # Can use attachment or inline

        # pdf generation logic here
        # open an existing pdf or generate one using i.e. reportlab

        return response

# Remove login_required if view open to public
display_pdf_view = login_required(DisplayPDFView.as_view())
要使用reportlab生成您自己的pdf,请参阅


Chris Pratt的回答显示了一个打开现有pdf的好例子。

如果您在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

Django有一个专门用于返回文件的类。它对文件进行流式处理,这样您就不必在返回文件之前将整个文件读入内存。给你:

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()
如果您有非常大的文件,或者您经常这样做,一个更好的选择可能是在Django之外使用正常的服务器配置来提供这些文件。

这对我很有用

import re, os
import os
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def export_auto_doc(request):
    name = request.GET.get('name', "")
    filename = "path/to/file"+name+".pdf"
    try:
        if not re.search("^[a-zA-Z0-9]+$",name):
            raise ValueError("Filename wrong format")
        elif not os.path.isfile(filename):
            raise ValueError("Filename doesn't exist")
        else:
            with open(filename, 'r') as pdf:
                response = HttpResponse(pdf.read(), content_type='application/pdf')
                response['Content-Disposition'] = 'inline;filename='+name+'.pdf'
                return response
            pdf.closed
    except ValueError as e:
        HttpResponse(e.message)

根据上面@radtek的回答,我决定研究基于类的视图显示。我试图使用
View
,但它没有
get\u context\u 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
评论

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

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

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

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


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

我只是把它扔出去

您只需将PDF简历添加到静态文件中即可。

如果您使用白噪声为静态文件提供服务,那么您甚至不需要创建视图。然后在静态位置访问您的简历

我加了我的,这是:


警告:这不能解决问题中的
登录要求
要求

最简单的方法可能是在模板中使用锚定。例如,如果您正在使用Django的模板引擎(大多数搜索该引擎的人可能都是这样),只需通过锚将其作为静态文件提供即可

在包含文件链接的模板中,在最顶部添加

{% load static %}
然后,无论你想链接到什么地方,把

<a href="{% static 'relative/path/file.pdf' %}">Click me</a>


第一行告诉Django在
settings.py
中查找为静态文件配置的目录。您在锚定标记中使用的路径相对于您在
settings.py
中配置为静态目录的任何目录。单击呈现的链接时,如果静态文件路径正确,它应该会在浏览器中显示PDF。

使用“r”打开并显示PDF对我很有效。即使在非Windows计算机上,最好使用
rb
而不是
r
,因为PDF文件不是文本文件。在我将
mimetype='application/PDF
更改为
contenttype='application/PDF'
content\u-type之前,它对我不起作用,同样,PDF.closed也无效there@azuax它在上下文处理器中,返回是否有
\uuuu exit\uuuu
调用?最好使用
rb
而不是
r
,因为PDF文件不是文本文件。不确定为什么会被否决。这就是我最后所做的,使用
{%load static%}
和一个带有
href=“{%url”file.pdf%}”的简单锚定
噢,我的错。这并不能完全回答问题。这不会在视图中显示PDF…除IE外,2019年的所有主要浏览器都支持原生PDF。