Как включить Reportlab с представлением на основе классов Django?

Я пытаюсь преобразовать свой HTML в PDF. Я просмотрел это руководство, https://www.codingforentrepreneurs.com/blog/html-template-to-pdf-in-django/, и мне удалось успешно заставить руководство работать с жестко запрограммированными значениями. Проблема в том ... Я не могу понять, как динамически включить мою модель и ее атрибуты в этот пример.

Вот шаги, которые я выполнил ...

Сначала я установил reportlab в свою среду со следующей версией ...

pip install --pre xhtml2pdf 

Это сработало ...

Затем я добавил в свой проект файл utils.py в соответствии с инструкциями.

Затем я скопировал этот код в свой файл utils.py ...

from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template

from xhtml2pdf import pisa

def render_to_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html  = template.render(context_dict)
    result = BytesIO()
    pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    return None

Затем я создал HTML-файл, подобный приведенному ниже:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>Title</title>
        <style type="text/css">
            body {
                font-weight: 200;
                font-size: 14px;
            }
            .header {
                font-size: 20px;
                font-weight: 100;
                text-align: center;
                color: #007cae;
            }
            .title {
                font-size: 22px;
                font-weight: 100;
               /* text-align: right;*/
               padding: 10px 20px 0px 20px;  
            }
            .title span {
                color: #007cae;
            }
            .details {
                padding: 10px 20px 0px 20px;
                text-align: left !important;
                /*margin-left: 40%;*/
            }
            .hrItem {
                border: none;
                height: 1px;
                /* Set the hr color */
                color: #333; /* old IE */
                background-color: #fff; /* Modern Browsers */
            }
        </style>
    </head>
    <body>
        <div class='wrapper'>
            <div class='header'>
                <p class='title'>Invoice # </p>
            </div>
        <div>
        <div class='details'>
            Bill to: {{ customer_name }} <br/>
            Amount: {{ amount }} <br/>
            Date: 
            <hr class='hrItem' />
        </div>
    </div>
    </body>
</html>

Я также создал необходимый URL ....

Затем я создал представление, подобное тому, что определено ниже:

from django.http import HttpResponse
from django.views.generic import View

from yourproject.utils import render_to_pdf #created in step 4

class GeneratePdf(View):
    def get(self, request, *args, **kwargs):
        data = {
             'today': datetime.date.today(), 
             'amount': 39.99,
            'customer_name': 'Cooper Mann',
            'order_id': 1233434,
        }
        pdf = render_to_pdf('pdf/invoice.html', data)
        return HttpResponse(pdf, content_type='application/pdf')

Когда я нажимаю ссылку на это представление ... результат отображается так же, как и сказано в руководстве ...

Однако, если я пытаюсь отобразить мою модель в этом формате ... Я не понимаю, как это сделать. Я попробовал DetailView .... а затем я получаю данные, но не PDF .... Я также искал много других мест и, похоже, не могу найти пример, который позволил бы мне динамически получить мою модель и вытащить в атрибутах по мере необходимости ... Заранее благодарим за любую помощь или указатели.


person Steve Smith    schedule 07.02.2019    source источник


Ответы (1)


Если вы хотите использовать DetailView, я думаю, вы можете сделать это так:

class SomeDetailView(DetailView):
    model = YourModel
    template_name = 'pdf/invoice.html'

    def get_context_data(self, **kwargs):
        context = super(SomeDetailView, self).get_context_data(**kwargs)
        # add extra context if needed
        return context

    def render_to_response(self, context, **kwargs):
        pdf = render_to_pdf(self.template_name, context)
        return HttpResponse(pdf, content_type='application/pdf')

Здесь я заменяю render_to_response, чтобы переопределить ответ по умолчанию от DetailView для возврата ответа PDF. Здесь контекст взят из get_context_data. в get_context_data при необходимости можно добавить любой дополнительный контекст.

person ruddra    schedule 07.02.2019
comment
Было бы супер, если бы можно было обобщить приведенный выше ответ на RL (как в заголовке) (здесь используется xhtml2pdf)? По сути, как бы вы могли успешно передать этот контекст и подключить его к переменным в шаблоне, отличном от html (RL использует (глобальные) переменные), например. как указано выше Data = {'amount': 39.99, '----- etc,} Объясняется, что Модель содержит Данные, и мы извлекаем эти данные контекста, но не то, как мы транспортируем этот контекст дальше в RL. Предположим, что в шаблоне, отличном от HTML, есть переменные, такие как «Amount», как вы назначите 39,99 из вашего контекста шаблону RL, отличному от HTML, перед печатью pdf? - person Jaco; 07.02.2019
comment
@ruddra Я использую этот метод также при создании своих PDF-файлов с использованием представления на основе классов, но я столкнулся с проблемой: я не могу отобразить моего текущего зарегистрированного пользователя в моем PDF-файле, я использовал {% if user .is_authenticated%}, но при рендеринге в PDF информация не отображается, например, если условие не было выполнено! есть ли какие-то дополнительные данные, которые мне нужно добавить в метод get_context_data? или это какое-либо поведение по умолчанию для рендеринга PDF? - person Luis Rodriguez; 02.06.2020
comment
Не могли бы вы задать новый вопрос по этому поводу с более подробной информацией о коде? Честно говоря, я сейчас не в контексте с reportlab, но уверен, что кто-то еще может помочь вам в этом вопросе. - person ruddra; 02.06.2020