wake-up-neo.com

Wie zeige ich ein PDF Datei in einer Django-Ansicht?

Ist es möglich, eine PDF -Datei in die Django-Ansicht anzuzeigen, anstatt dass der Benutzer sie herunterladen muss, um sie anzuzeigen?

Und wenn es möglich ist, wie würde es gemacht?

Das habe ich bis jetzt - 

@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
25
SImon

Wenn Sie eine PDF -Datei haben und diese über eine Django-Ansicht ausgeben möchten, müssen Sie lediglich den Inhalt der Datei in die Antwort speichern und sie mit dem entsprechenden Mimetyp senden.

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

Sie können die Antwort wahrscheinlich nur direkt zurückgeben, ohne Content-Disposition anzugeben. Dies zeigt jedoch besser Ihre Absicht an und ermöglicht Ihnen auch die Angabe des Dateinamens, falls der Benutzer sie speichern möchte.

Beachten Sie außerdem, dass in der obigen Ansicht nicht das Szenario behandelt wird, in dem die Datei aus irgendeinem Grund nicht geöffnet oder gelesen werden kann. Da dies mit with erledigt ist, werden keine Ausnahmen ausgelöst, Sie müssen jedoch eine Antwort zurückgeben. Sie können jedoch einfach einen Http404 oder etwas erhöhen.

29
Chris Pratt

Django hat eine Klasse speziell für die Rückgabe von Dateien, FileResponse . Es streamt Dateien, sodass Sie nicht die gesamte Datei in den Speicher lesen müssen, bevor Sie sie zurückgeben. Bitte schön:

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()

Wenn Sie wirklich große Dateien haben oder dies häufig tun, ist es wahrscheinlich eine bessere Option, diese Dateien mit normaler Serverkonfiguration außerhalb von Django bereitzustellen.

20
Flimm

Wenn Sie auf einem Windows-Computer arbeiten, muss das PDF als rb und nicht r geöffnet werden.

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
8
MKM

Inline herausnehmen; wenn Sie möchten, dass Ihre Datei vom Server gelesen wird. Außerdem wurde HttpResponse kwarg mimetype durch content_type ersetzt:

(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
5
gajanan hegde

Nach der Antwort von @ radtek habe ich mich entschlossen, eine klassenbasierte Ansichtsanzeige zu untersuchen. Ich habe versucht, View zu verwenden, aber es gab keine get_context_data()-Methode.

Ich habe hier nach einigen Anleitungen gesucht. Ich entschied mich für BaseDetailView, da ich nur ein Objekt anzeigen wollte.

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

Kommentar

1 Diese Zeile greift auf ein benanntes Argument pk zu, das von der URL übergeben wird, die die Ansicht aufruft.

2 Diese Zeile enthält das eigentliche PDF-Modellobjekt.

3 Ich habe in meinem Modell eine Methode filename(self): return os.path.basename(self.file.name) definiert, die mir dabei hilft, nur den Dateinamen und die Erweiterung zu erhalten.

4 Diese Zeile enthält den vollständigen Dateipfad.

Verwenden Sie dann die Dateiantwort, wie in den obigen Antworten beschrieben. Denken Sie auch daran, rb zum Lesen der PDF-Datei zu verwenden

3
chidimo

Hier ein typischer Anwendungsfall für das Anzeigen von PDF mithilfe von klassenbasierten Ansichten:

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())

Zum Erstellen eines eigenen PDFs mit reportlab siehe das Django-Projekt Docs auf PDF Generation .

Die Antwort von Chris Pratt zeigt ein gutes Beispiel für das Öffnen vorhandener PDF-Dateien.

2
radtek

Browser sind keine PDF -Leser (es sei denn, sie verfügen über das richtige Plugin/Addon).

Möglicherweise möchten Sie die PDF stattdessen als HTML rendern. Dies kann vom Backend oder vom Frontend erfolgen.

0
Gonzalo

es hat für mich funktioniert

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)
0
German Lopez