How to incorporate Reportlab with Django Class Based View?

走远了吗. 提交于 2019-12-11 18:45:39

问题


I am trying to convert my HTML to a PDF. I watched this tutorial, https://www.codingforentrepreneurs.com/blog/html-template-to-pdf-in-django/ and I was able to successfully get the tutorial to work with hardcoded values. The problem is...I can't figure out how to dynamically incorporate my model and it's attributes into this example.

Here are the steps I followed...

First I installed reportlab into my environment with the following version...

pip install --pre xhtml2pdf 

This worked...

Then I added a utils.py file to my project as instructed.

Then I copied this code into my utils.py file...

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

Then I created an HTML file like the one below:

<!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>

I also created the necessary URL....

Then I created a view similar to what is defined below:

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')

When I click on my link to this view...the output shows just like the tutorial says...

However, if I am trying to get my model to display in this format...I'm stumped as to how to do that. I tried a DetailView....and then I get the data but no PDF....I've also searched many other places and I can't seem to find an example that would allow me to get my model dynamically and pull in attributes as needed...Thanks in advance for any help or pointers.


回答1:


If you want to use DetailView, I think you can do it like this:

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')

Here I am overriding render_to_response to override the default response from DetailView to return a PDF response. Here, the context that comes in are from get_context_data. in get_context_data you can add any extra context if needed.



来源:https://stackoverflow.com/questions/54565679/how-to-incorporate-reportlab-with-django-class-based-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!