2012-08-02 28 views
15

Czy można wyświetlić plik PDF w widoku Django w widoku, zamiast zmuszać użytkownika do pobrania go, aby go wyświetlić?Jak wyświetlić plik PDF w widoku Django?

A jeśli to możliwe, w jaki sposób byłoby to możliwe?

To, co mam tak daleko -

@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 

Odpowiedz

23

Upraszczając, jeśli masz plik PDF i chcesz wstawić go przez widok Django, wszystko co musisz zrobić, to zrzucić zawartość pliku do odpowiedź i wyślij go za pomocą odpowiedniego typu MIME.

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 

Prawdopodobnie można tylko odesłać odpowiedź bezpośrednio bez określania Content-Dyspozycja, ale wskazuje, że lepiej swój zamiar, a także pozwala określić nazwę pliku tylko w przypadku, gdy użytkownik zdecyduje się go uratować.

Należy również zauważyć, że powyższy widok nie obsługuje scenariusza, w którym nie można otworzyć pliku lub go odczytać z jakiegokolwiek powodu. Ponieważ jest to zrobione z with, nie spowoduje żadnych wyjątków, ale nadal musisz zwrócić jakąś odpowiedź. Można jednak po prostu podnieść Http404 lub coś podobnego.

+0

To nie działa na mnie, dopóki nie zmieniłem 'mimetype = "application/pdf" to "contenttype =" application/pdf'' –

+2

content_type, również pdf.closed nie ma tam żadnego efektu – amchugh89

+0

czy to jest w porządku, zanim zamkniesz plik ??? Myślę, że nie. – azuax

1

Przeglądarki nie są czytnikami PDF (chyba że mają odpowiednią wtyczkę/dodatek).

Możesz zamiast tego renderować PDF jako HTML, który można wykonać jako from the backend lub the frontend.

5

Wyjmij w linii; jeśli chcesz, aby twój plik był odczytywany z serwera. A Również HttpResponse kwarg mimetype został zastąpiony przez 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

Oto typowy use-case do wyświetlania plików PDF za pomocą widoki klasy opartej:

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

Do generowania własnych pdf z reportlab zobacz Django project Docs on PDF Generation.

Odpowiedź Chris Pratt pokazuje dobry przykład otwarcia istniejących plików PDF.

6

Jeśli pracujesz na komputerze z systemem Windows, plik PDF musi być otwarty jako rb, a nie 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

Otwieranie i pokazywanie pdf pracował dla mnie przy użyciu "r". – yndolok

10

Django ma klasę przeznaczoną specjalnie do zwracania plików, FileResponse. Przesyła pliki strumieniowo, dzięki czemu nie trzeba czytać całego pliku w pamięci przed zwróceniem go. Proszę bardzo:

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

Jeśli masz naprawdę duże pliki lub jeśli robisz to dużo, lepszym rozwiązaniem byłoby prawdopodobnie służą te pliki poza Django stosując normalną konfigurację serwera.

0

pracował dla mnie

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

następującą odpowiedź @ radtek za wyżej postanowiłem zbadać widok wyświetlacza klasy oparte. Próbowałem użyć View, ale nie miałem metody get_context_data().

Dla niektórych wskazówek wyglądałem na here. Zdecydowałem się na BaseDetailView, ponieważ chciałem wyświetlić tylko jeden obiekt.

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 

Komentarz

1 Ta linia dostęp nazwanego argumentu pk przekazywana przez URL wywołującego widoku.

2 Ta linia pobiera rzeczywisty obiekt modelu pdf.

3 W moim modelu zdefiniowałem metodę filename(self): return os.path.basename(self.file.name), która pomoże mi uzyskać samą nazwę pliku i rozszerzenie.

4 Ta linia otrzymuje pełną ścieżkę do pliku.

Następnie użyj odpowiedzi na plik, jak wyjaśniono w powyższych odpowiedziach. Pamiętaj też, aby użyć pliku rb, aby przeczytać plik PDF:

-1

Po prostu to wyrzucam.

Możesz po prostu dodać swoje CV PDF do swoich plików statycznych.

Jeśli używasz White Noise do wyświetlania statycznych plików, nie musisz nawet tworzyć widoku. Wystarczy wtedy uzyskać dostęp do CV w statycznej lokalizacji.

dodałam mój, oto ona: https://www.jefferythewind.com/static/main/resume/TIm-D_Nice.pdf

Ostrzeżenie: To nie rozwiąże wymóg login_required w pytaniu

Powiązane problemy