ReportLab:使用不同的kwargs多次调用相同的PageTemplate?

时间:2018-03-26 19:05:27

标签: python pdf pdf-generation reportlab

是否可以在一个doc.build中多次调用相同的PageTemplate?

例如,如果您在页眉和页脚中使用订单实例属性的订单有PageTemplate,那么您将如何创建给定日期的所有订单的PDF?

class OrderTemplate(BaseDocTemplate):
    def __init__(self, filename, **kwargs):
        self.order = kwargs['order']
        BaseDocTemplate.__init__(self, filename **kwargs)
        main_frame = Frame(0, 0, self.pagesize[0], self.pagesize[1], id='main_frame')
        template = PageTemplate(id='header_footer_frame', frames=[main_frame], 
                                onPage=self.header_footer)
        self.addPageTemplates([template])

        # title
        canvas.setFont('Helvetica', 12)
        company_name = self.order.name.upper()
        first_row = canvas.beginText(0, doc.pagesize[1] - 10)
        first_row.textLine(company_name)
        canvas.drawText(first_row)

class Report:
    @staticmethod
    def build_pdf(**kwargs):
        buffer = BytesIO()
        doc = OrderTemplate(buffer, pagesize=kwargs['pagesize'], 
                            title=kwargs['page_title'],
                            order=kwargs['order'])

        doc.build(kwargs['story'], canvasmaker=NumberedCanvas)

        # Get the value of the BytesIO buffer and write it to the response.
        pdf = buffer.getvalue()
        buffer.close()
        return pdf

    @staticmethod
    def build_order(**kwargs):
        orders = kwargs['orders']
        pagesize = letter

        # Flow-able content
        story = []

        for order in orders:
            lines = OrderLine.objects.filter(order=order).order_by('pk')
            story.append(table)
            story.append(PageBreakIfNotEmpty())

        return Report.build_pdf(pagesize=pagesize, page_title=page_title, 
                                story=story, template=template, order=order)

build_order()方法为每个订单生成一个页面,其中包含正确的关联行,但每个页面的页眉/页脚都相同。我需要以某种方式为每个循环调用PageTemplate并将其传递给新的命令kwargs。

1 个答案:

答案 0 :(得分:0)

根据ReportLab用户指南rltemplate.py

中章节的使用,我得到了解决方案
class OrderTemplate(PageTemplate):
    def __init__(self, id, pagesize=letter):
        frame = Frame(0, 0, pagesize[0], pagesize[1], id='main_frame')
        PageTemplate.__init__(self, id, [frame])

    def afterDrawPage(self, canvas, doc):
        canvas.saveState()
        canvas.setPageSize(doc.pagesize)
        canvas.setTitle(doc.title)

        if doc.order:
            # title
            canvas.setFont('Helvetica', 12)
            company_name = doc.order.name.upper()
            first_row = canvas.beginText(0, doc.pagesize[1] - 10)
            first_row.textLine(company_name)
            canvas.drawText(first_row)

        canvas.restoreState()

class BatchPrintTemplate(BaseDocTemplate):
    def __init__(self, filename, **kwargs):
        self.orders = kwargs['orders']
        self.order_iter = iter(self.orders)
        BaseDocTemplate.__init__(self, filename, **kwargs)

    def beforeDocument(self):
        self.order = next(self.order_iter)

    def afterInit(self):
        self.addPageTemplates(OrderTemplate('Order', pagesize=self.pagesize))

    def afterFlowable(self, flowable):
        if hasattr(flowable, 'new_order'):
            try:
                self.order = next(self.order_iter)
            except StopIteration:
                pass

构建Flowable时,您必须使用new_order属性标记每个分页符。设置要在标头中使用的下一个订单由afterFlowable处理。

class BatchPrint:
    def build_pdf(**kwargs):
        buffer = BytesIO()
        doc = BatchPrintTemplate(buffer, pagesize=kwargs['pagesize'], title=kwargs['page_title'],
                                 orders=kwargs['orders'])
        doc.build(kwargs['story'])
        # Get the value of the BytesIO buffer and write it to the response.
        pdf = buffer.getvalue()
        buffer.close()
        return pdf

    def build_orders(**kwargs):
        story = []
        for order in orders:
            ## build your flowables here ##
            story.append(table)

            story.append(PageBreak())
            story[-1].new_order = True

        return BatchPrint.build_pdf(pagesize=pagesize, page_title=page_title, story=story, orders=orders)