2012-08-02 3 views
15

E 'possibile mostrare un file PDF in la vista di Django, piuttosto che fare l'utente deve scaricarlo per vederlo?Come mostrare un file PDF in una vista Django

E se è possibile, come sarebbe fatto?

Questo è quello che ho finora -

@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 

risposta

23

Semplificando, se si dispone di un file PDF e si desidera l'uscita attraverso una vista Django, tutto quello che dovete fare è scaricare il contenuto del file nel risposta e inviarlo con il mimetype appropriato.

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 

Si può probabilmente solo restituire la risposta direttamente senza specificare Content-Disposition, ma che meglio indica la vostra intenzione e consente inoltre di specificare il nome del file nel caso in cui l'utente decida di salvarlo.

Si noti inoltre che la vista di cui sopra non gestisce lo scenario in cui il file non può essere aperto o leggere per qualsiasi motivo. Dato che è fatto con with, non genererà alcuna eccezione, ma è comunque necessario restituire una sorta di risposta. Si potrebbe semplicemente aumentare un Http404 o qualcosa, però.

+0

Non funziona per me fino a quando ho cambiato 'mimetype = 'application/pdf' a 'contenttype =' application/pdf'' –

+2

content_type, anche pdf.closed non ha effetto lì – amchugh89

+0

okay il ritorno prima di chiudere il file ??? Penso di no. – azuax

1

browser non sono lettori PDF (a meno che non abbiano il corretto plugin/addon).

Si consiglia di eseguire il rendering del PDF in formato HTML, che può essere eseguito from the backend o the frontend.

5

Estrarre in linea; se vuoi che il tuo file venga letto dal server. E inoltre, il HttpResponse kwarg mimetype è stato sostituito da 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 
1

Ecco un caso d'uso tipico per la visualizzazione di un file PDF utilizzando le visualizzazioni di classe a base di:

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

Per generare il proprio pdf con reportlab vedere lo Django project Docs on PDF Generation. La risposta di

Chris Pratt mostra un buon esempio di aprire file PDF esistenti.

6

Se si sta lavorando su una macchina Windows, il pdf deve essere aperto come rb non 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 
+0

Aprire e mostrare il pdf ha funzionato con me usando 'r'. – yndolok

10

Django ha una classe specifica per la restituzione dei file, FileResponse. Trasmette i file, in modo da non dover leggere l'intero file in memoria prima di restituirlo. Qui si va:

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

Se si dispone di file di grandi dimensioni davvero o se si sta facendo questo un sacco, una soluzione migliore sarebbe probabilmente quella di servire questi file al di fuori di Django utilizzando la configurazione del server normale.

0

ha funzionato per me

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

seguente risposta di @ radtek sopra ho deciso di indagare un display vista della classe-based. Ho provato a utilizzare View ma non aveva il metodo get_context_data().

Ho cercato here per qualche consiglio. Ho optato per BaseDetailView poiché volevo visualizzare solo un oggetto.

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 

Commento

1 Questa linea accessi un argomento di nome pk approvata dal URL chiamando la vista.

2 Questa riga ottiene l'oggetto modello pdf effettivo.

3 Ho definito un metodo filename(self): return os.path.basename(self.file.name) nel mio modello per aiutarmi a ottenere solo il nome file e l'estensione.

4 Questa riga ottiene il filepath completo.

Quindi utilizzare la risposta del file come spiegato nelle risposte precedenti. Ricorda inoltre di utilizzare rb per leggere il file pdf

-1

Sto lanciando questo fuori.

È sufficiente aggiungere il curriculum PDF ai file statici.

Se si utilizza White Noise per servire i file statici, quindi non avrete nemmeno bisogno di fare la vista. Solo allora accedi al tuo curriculum nella posizione statica.

ho aggiunto il mio, eccolo: https://www.jefferythewind.com/static/main/resume/TIm-D_Nice.pdf

Attenzione: questo non risolve il requisito login_required nella questione