elapouya / python-docx-template

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

feature request: image size and path from template #191

Open sanzoghenzo opened 5 years ago

sanzoghenzo commented 5 years ago

Thanks for this great library!

I would like the user to be able to set the size of the image directly in the template, instead of hardcoding it.

It would be nice to be able to set the path of the image from the template, also.

Maybe a custom filter image(width=None, height=None) that automatically creates an InlineImage with the provided size?

That way one could specify {{ <path> | image(width, height) }}.

albertix commented 5 years ago

Is it possible to get tpl from jinja filter?

%tpl.docx

{{ path | image(width, height) }}

then

from docxtpl import InlineImage
from docxtpl import DocxTemplate
from docx.shared import Mm
import jinja2

jinja_env = jinja2.Environment()

def image(ctx, path, width=None, height=None):
    # get tpl from jinja_env
    tpl = ctx['tpl']
    return InlineImage(tpl, path, width=Mm(width), height=Mm(height))

jinja_env.filters['image'] = image

context = {'path' : './xx.jpg' }

tpl=DocxTemplate('tpl.docx')
tpl.render(context, jinja_env)
tpl.save('output.docx')
albertix commented 5 years ago

tricky way

def image(path, tpl=None, width=None, height=None):
    if tpl:
        width = Mm(width) if width else None
        height = Mm(height) if height else None
        return InlineImage(tpl, path, width=width, height=height)
    else:
        return ""

jinja_env.filters['image'] = image
context = {'path': path, 'tpl': doc}
doc.render(context, jinja_env)
open-dynaMIX commented 4 years ago

I was able to get this working with the @contextfilter decorator:

@contextfilter
def image(ctx, path, width=None, height=None):
    tpl = ctx["_tpl"]
    ...

Then I just had to add the template to the context: context["_tpl"] = template.

lFitzl commented 2 years ago

In case someone needs this with the most modern syntax...


from jinja2.utils import pass_context

@pass_context
def imagen(ctx, path, width=None, height=None):
        from docxtpl import InlineImage
        from docx.shared import Mm
        tpl = ctx["_tpl"]
        if tpl:
            width = Mm(width) if width else None
            height = Mm(height) if height else None
            return InlineImage(tpl, path, width=width, height=height)
        else:
            return ""

PD: Deprecated since version 3.0: Will be removed in Jinja 3.1. Use pass_context() instead.

bullfrog-au commented 3 months ago

I second this. The solutions suggested by others will work just fine for my use case, but a nice native handling of image size using context of the destination would make it cleaner.

Awesome library though, thankyou!!