elapouya / python-docx-template

Use a docx as a jinja2 template
GNU Lesser General Public License v2.1
1.91k stars 378 forks source link

Reusing a page from a template #459

Open mbaksa opened 1 year ago

mbaksa commented 1 year ago

I could open a template, and render it with a provided context. In my case, a template is a single page, lets say like an article - category, title, text, image.

Can the page of this template be reused with a different context, for multiple articles in the same document? I need 8-9 pages based on the same template. So I would iterate through contexts with Python to provide data (pulled from an Excel file), but how can I have all those filled pages in a single document?

Is there a sensible way to do it? I mean, the same way one template or one page of template can be rendered once, shouldn't be there a way to do it multiple times, and put page-break before each further page? I really don't want to render 8-9 .docx files and then merge them with some other tool, or try to figure out if that is possible using complicated stuff in jinja. I'm new to all this, and couldn't find a way to do it.

elapouya commented 1 year ago

Actually, there is no "include feature". BUT Let's say you have one document with many articles : you can use a for-loop in your template. Inside which you display informations for the current for-loop article. At python level, you just have to specify in the context a list of articles...

mbaksa commented 1 year ago

Thank you for trying to help. If that's even possible to do (I don't know - I'm only starting with Python), that is not a good solution, since it adds unnecessary complication to templates, and templates should be as simple and clear as possible. But I've worked out a good solution. In this solution, I iterate through contexts, render a template for each context, and append one after the other using composer. Page break is added after every rendering, unless it's the last page. Maybe add this solution to the documentation of your project?

from docxcompose.composer import Composer
from docxtpl import DocxTemplate
from docx import Document

contexts = [
{
    'title' : 'Title of 1st article',
    'text' : 'Brilliant text of the 1st article'
},
{
    'title' : 'Title of 2nd article',
    'text' : 'The text of the 2nd article'
}]

composer = None

for index, context in enumerate(contexts):
    doc = DocxTemplate("template.docx")
    doc.render(context)

    if index < len(contexts) - 1:
        doc.add_page_break()

    if not composer:
        composer = Composer(doc)    
    else:
        composer.append(doc)

composer.save("rendered_and_merged.docx")