Nested Templates?
Is it possible for you to implement functionality to do nested templates, maybe with subdocs?
Basically, I want to have a main template with several jinja tags. Then I would like to define tables in a few other template files, each containing jinja tags. Finally, I would like to pull records from a database, and then loop through them, creating a table in the main doc for each record, based on a table template. I can do this with the existing code base, but I have to build the tables in my script as opposed to defining them in a Word template. I hope that makes sense.
I have a function to use word files as snipplets:
def __ext_snipplet(self, name):
"""
Render another docx body into my document
"""
document = DocxTemplate(self.getSnippletPath(name))
document.render(self.jinjaContext)
# Remove the sectPr element ("SecrionProperties")
# "This element defines the section properties for the final section of the document." (Source: https://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.sectionproperties(v=office.14).aspx)
# This is not needed in case of a snipplet
if document._element.body.sectPr is not None:
document._element.body.remove(document._element.body.sectPr)
# Remove the body xml tag
xml = re.sub(r'</?w:body[^>]*>', '', document.get_xml())
return xml
You have to add it to the jinja context:
self.jinjaContext.update({'snipplet': self.__ext_snipplet})
Then, in your template you can call other word files. They will be rendered too:
{{p snipplet('SNIP1.docx') }}
But this function has some problems:
- Different formats (color and tables and so on) of the sinipplet files are not copied.
- Images of the snipplets are not copied. The code should copy the image files (and other attachements) into the base document and assign a new, free id in the xml.
snipplet.docx snipplet_snip.docx snipplet_tpl.docx
snipplet.py:
from ls.docxtpl import DocxTemplate
tpl = DocxTemplate('test_files/snipplet_tpl.docx')
tpl.render({'a': 'abc'})
tpl.save('test_files/snipplet.docx')
Maybe there are some other problems. Use it with care. Feel free to improve the code.
Hello,
The main template stores all images and styles, creating sub-templates can import some texts or tables, but I do not know yet how to merge sub template images and styles into the main template : this step is part of the library "python-docx" I am using.
Using subdoc can help a little : you have to build your table from scratch : if your tables are simple, it could do the job (have a look to python-docx documentation and the docxtpl/tests/subdoc.py)
But the real sub-templating is not fully possible now : one have to merge maindoc._part with subtamplatedoc._part, thing I do not kown how to proceed.
Thanks for the suggestions. elapouya - I've been generating tables from scratch via subdocs. It works well, but it's not as flexible as I'd like.
Denny - your function is working quite well for me so far. I'm able to create separate template files, each with tables containing tags, and then pull them into the main document.
Denny - do you have any examples of how you're copying images from a snipplet into the base document? EDIT Nevermind on this last question - I figured it out.
@fixautomator Could you please share how you got the images into the base document? I am having the same problem.
@dalai4git
I basically loop through the context before I render, looking for images and replacing them with InlineImage. Here's kind of a hacky example:
for item in context['screenshots']: if type(item.image) != InlineImage and '<wp:inline' not in item.image: item.image = InlineImage(document, item.image)
@DennyWeinberg
Could you pls. update your example to have a full functional code ? I don't understand how should I update the jinja context (how do I obtain the instance of the jinja context to be more precise)
@exfiltrata ,hi, have you worked out inserting with not constant number of subdocs? thanks a lot