2012-08-02 131 views
15

¿Es posible mostrar un archivo PDF en la vista de Django, en lugar de hacer que el usuario tenga que descargarla para verla?Cómo mostrar un archivo PDF en una vista de Django

Y si es posible, ¿cómo se haría?

Esto es lo que tengo hasta ahora -

@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 

Respuesta

23

manera simplista, si usted tiene un archivo PDF y desea dar salida a través de una vista de Django, todo lo que necesita hacer es volcar el contenido del archivo en el respuesta y enviarlo con el tipo de mime apropiado.

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 

probablemente puede devolver la respuesta directamente sin especificar Content-Disposition, pero que mejor indica su intención y también le permite especificar el nombre del archivo en caso de que el usuario decide guardarla.

Además, tenga en cuenta que la vista anterior no maneja el escenario donde el archivo no se puede abrir o leer por cualquier razón. Dado que está hecho con with, no generará ninguna excepción, pero aún debe devolver algún tipo de respuesta. Sin embargo, simplemente podría elevar un Http404 o algo así.

+0

No funciona para mí hasta que me he cambiado 'MIME = 'application/pdf' to 'contenttype =' application/pdf'' –

+2

content_type, también pdf.closed no tiene ningún efecto allí – amchugh89

+0

¿está bien la devolución antes de cerrar el archivo? Yo creo que no. – azuax

1

Los navegadores no son lectores de PDF (a menos que tengan el plugin/complemento adecuado).

Es posible que desee representar el PDF como HTML en su lugar, lo que se puede hacer from the backend o the frontend.

5

Take inline; si quieres que tu archivo se lea desde el servidor. Y también, el HttpResponse kwarg mimetype ha sido reemplazado por 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

Aquí es un caso de uso típico para la visualización de un archivo PDF utilizando puntos de vista basados ​​en la clase:

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

Para generar su propia pdf con reportlab, vea el Django project Docs on PDF Generation.

La respuesta de Chris Pratt muestra un buen ejemplo de apertura de archivos PDF existentes.

6

Si está trabajando en una máquina con Windows, el pdf debe abrirse como rb y no 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

Abriendo y mostrando el pdf funcionó para mí usando 'r'. – yndolok

10

Django tiene una clase específica para la devolución de archivos, FileResponse. Transmite archivos, para que no tenga que leer todo el archivo en la memoria antes de devolverlo. Aquí van:

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

Si tiene archivos muy grandes o si está haciendo esto mucho, una mejor opción sería probablemente para servir a estos archivos fuera de Django usando la configuración del servidor normal.

0

que trabajó para mí

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

siguiente respuesta de @ radtek anterior decidí investigar una pantalla de lectura clasista. Traté de usar View pero no tenía el método get_context_data().

Miré here para obtener orientación. Me conformé con BaseDetailView ya que quería mostrar solo un objeto.

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 

Comentario

1 Esta línea tiene acceso a un argumento con nombre pk aprobada por la URL llamando a la vista.

2 Esta línea obtiene el objeto del modelo pdf real.

3 Definí un método filename(self): return os.path.basename(self.file.name) en mi modelo para ayudarme a obtener solo el nombre de archivo más la extensión.

4 Esta línea obtiene la ruta de archivo completa.

A continuación, utilice la respuesta del archivo como se explica en las respuestas anteriores. También recuerde usar rb para leer el archivo pdf

-1

Estoy tirando esto por ahí.

Puede simplemente agregar su currículum de PDF a sus archivos estáticos.

Si está utilizando White Noise para servir sus archivos estáticos, entonces ni siquiera necesita hacer la vista. Solo entonces acceda a su currículum en la ubicación estática.

he añadido mío, aquí está: https://www.jefferythewind.com/static/main/resume/TIm-D_Nice.pdf

Advertencia: Esto no resuelve el requisito login_required en la pregunta

Cuestiones relacionadas