it-roy-ru.com

Как показать PDF файл в представлении Django?

Можно ли показать PDF файл in представление Django, вместо того, чтобы заставить пользователя загрузить его, чтобы увидеть его?

И если это возможно, как это будет сделано?

Это то, что я до сих пор - 

@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
25
SImon

Проще говоря, если у вас есть файл 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 или что-то еще.

29
Chris Pratt

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 с использованием обычной конфигурации сервера.

20
Flimm

Если вы работаете на компьютере с Windows, pdf должен быть открыт как rb, а не 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
8
MKM

Вынуть в линию; если вы хотите, чтобы ваш файл читался с сервера. А также, 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
gajanan hegde

Следуя ответу @ 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

3
chidimo

Вот типичный вариант использования для отображения 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 в PDF Generation .

Ответ Криса Пратта показывает хороший пример открытия существующих PDF-файлов.

2
radtek

Браузеры не являются PDF читателями (если у них нет подходящего плагина/дополнения).

Вы можете вместо этого визуализировать PDF как HTML, что можно сделать из внутреннего интерфейса или из внешнего интерфейса .

0
Gonzalo

это сработало для меня

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
German Lopez