Как показать файл PDF в представлении Django
Возможно ли показать файл PDF в представлении Django, а не заставить пользователя загружать его, чтобы увидеть его?
И если это возможно, как это сделать?
Это то, что у меня есть до сих пор -
@login_required
def resume(request, applicant_id):
#Get the applicant resume
resume = File.objects.get(applicant=applicant_id)
fsock = open(resume.location, 'r')
response = HttpResponse(fsock, mimetype='application/pdf')
return response
Ответы
Ответ 1
Упростительно, если у вас есть файл PDF, и вы хотите вывести его через представление Django, все, что вам нужно сделать, это выгрузить содержимое файла в ответ и отправить его с соответствующим типом mimetype.
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
Вы можете, возможно, просто вернуть ответ напрямую, не указав Content-Disposition, но это лучше указывает на ваше намерение, а также позволяет указать имя файла на случай, если пользователь решит его сохранить.
Также обратите внимание, что приведенное выше представление не обрабатывает сценарий, в котором файл не может быть открыт или прочитан по какой-либо причине. Поскольку это сделано с помощью with
, оно не будет создавать никаких исключений, но вы все равно должны вернуть какой-то ответ. Вы могли бы просто поднять Http404
или что-то еще.
Ответ 2
Django имеет класс, специально предназначенный для возврата файлов, FileResponse. Он передает файлы, так что вам не нужно читать весь файл в памяти, прежде чем возвращать его. Вот вы:
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()
Если у вас действительно большие файлы или если вы делаете это много, лучшим вариантом будет, вероятно, обслуживание этих файлов за пределами Django с использованием обычной конфигурации сервера.
Ответ 3
Если вы работаете с Windows-машиной, то файл pdf должен быть открыт как rb
not 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
Ответ 4
Выньте встроенный; если вы хотите, чтобы ваш файл читался с сервера. Кроме того, HttpResponse
kwarg mimetype
был заменен на 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
Ответ 5
Браузеры не являются читателями в формате PDF (если у них нет надлежащего плагина/аддона).
Возможно, вы захотите сделать PDF как HTML, что можно сделать из бэкэнд или интерфейс.
Ответ 6
Вот типичный пример использования для отображения PDF с использованием представлений на основе классов:
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())
Для создания собственного pdf с помощью reportlab см. Django Docs в PDF Generation.
Ответ Криса Пратта показывает хороший пример открытия существующих PDF файлов.
Ответ 7
это сработало для меня
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)
Ответ 8
Следуя приведенному выше решению @radtek, я решил исследовать отображение на основе класса. Я попытался использовать View
, но у него не было метода get_context_data()
.
Я посмотрел здесь для некоторых рекомендаций. Я остановился на BaseDetailView
, так как хотел отобразить только один объект.
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
Комментарий
1 Эта строка обращается к именованному аргументу pk
, переданному по URL-адресу, вызывающему представление.
2 Эта строка получает фактический объект модели pdf.
3 Я определил метод filename(self): return os.path.basename(self.file.name)
в моей модели, чтобы помочь мне получить только имя файла плюс расширение.
4 Эта строка получает полный путь к файлу.
Затем используйте ответ файла, как описано в ответах выше. Также не забудьте использовать rb
для чтения pdf файла
Ответ 9
Я просто бросаю это там.
Вы можете просто добавить свое PDF-резюме в свои статические файлы.
Если вы используете Белый шум для обслуживания ваших статических файлов, вам даже не нужно делать представление. Просто войдите в свое резюме в статическом месте.
Я добавил мой, вот он: https://www.jefferythewind.com/static/main/resume/TIm-D_Nice.pdf
Предупреждение. Это не разрешает требование login_required
в вопросе