Est-il possible d'afficher un fichier PDF dans la vue Django, plutôt que de demander à l'utilisateur de le télécharger pour le voir?
Et si c'était possible, comment cela serait-il fait?
C'est ce que j'ai jusqu'à présent -
@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
De manière simpliste, si vous avez un fichier PDF et que vous voulez le sortir via une vue Django, il vous suffit de vider le contenu du fichier dans la réponse et de l'envoyer avec le type MIME approprié.
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
Vous pouvez probablement simplement renvoyer la réponse directement sans spécifier Content-Disposition, mais cela indique mieux votre intention et vous permet également de spécifier le nom du fichier au cas où l'utilisateur déciderait de l'enregistrer.
Notez également que la vue ci-dessus ne gère pas le scénario dans lequel le fichier ne peut pas être ouvert ou lu pour une raison quelconque. Etant donné que cela est fait avec with
, cela ne soulève aucune exception, mais vous devez quand même renvoyer une sorte de réponse. Vous pouvez simplement élever un Http404
ou autre chose.
Django a une classe spécialement conçue pour renvoyer des fichiers, FileResponse . Il diffuse les fichiers afin que vous n'ayez pas à lire le fichier en entier avant de le renvoyer. Voici:
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 vous avez des fichiers très volumineux ou si vous le faites souvent, une meilleure option serait probablement de les servir en dehors de Django en utilisant une configuration de serveur normale.
Si vous travaillez sur une machine Windows, le fichier PDF doit être ouvert sous la forme rb
et 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
Sortez en ligne; si vous voulez que votre fichier soit lu depuis le serveur. Et aussi, la HttpResponse
kwarg mimetype
a été remplacée par 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
Suite à la réponse de @ radtek ci-dessus, j'ai décidé d'étudier un affichage de vue basé sur les classes. J'ai essayé d'utiliser View
mais il n'y avait pas de méthode get_context_data()
.
J'ai cherché ici pour des conseils. Je me suis installé pour BaseDetailView
car je ne voulais afficher qu'un seul objet.
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
Commentaire
1 Cette ligne accède à un argument nommé pk
transmis par l'URL appelant la vue.
2 Cette ligne récupère l'objet de modèle pdf réel.
3 J'ai défini une méthode filename(self): return os.path.basename(self.file.name)
dans mon modèle pour m'aider à obtenir uniquement le nom de fichier plus l'extension.
4 Cette ligne obtient le chemin complet du fichier.
Ensuite, utilisez la réponse de fichier comme expliqué dans les réponses ci-dessus. Pensez également à utiliser rb
pour lire le fichier pdf.
Voici un cas d'utilisation typique pour afficher un PDF à l'aide de vues basées sur des classes:
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())
Pour générer votre propre fichier PDF avec reportlab, consultez la documentation du projet Django sur PDF Generation .
La réponse de Chris Pratt montre un bon exemple d'ouverture de fichiers PDF existants.
Les navigateurs ne sont pas PDF lecteurs (à moins qu'ils aient le plug-in/addon approprié).
Vous voudrez peut-être rendre le PDF au format HTML à la place, ce qui peut être fait à partir du serveur ou du serveur .
ça a fonctionné pour moi
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)