Как показать файл 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 в вопросе