Reusable Jinja/template helpers

I find myself copy/pasting really similar templates across automations, cards, etc.

I’d like a way to easily add new Jinja filters or reusable templates (either would solve my use cases). This does not necessarily mean using the UI.

For clarification, I assume:

  • a Jinja filter means defining the filter using Python
  • a “reusable template” would essentially be a global variable that contains a template string. It can be used in other template strings.

Sorry if this was already suggested or already doable another way. If it is, I’d be happy to contribute documentation for it.

While I would love this, I think it falls into a new integration that’s loaded prior to templates, and potentially loaded as one of the first integrations at startup so that MQTT, Rest, etc, can take advantage of it.

2 Likes

I’m not a Python dev and certainly not familiar with home-assistant/core, so what I was thinking may not be possible or bad practice…

Would it be possible for this method to try importing a file at a known location. If the file can be imported, there should be an implemented class that adds additional filters.

3 Likes

The ability to create macros and reuse them would be great in the yaml. Having macros without the option to reuse them in other places, makes them very unusable.

I see this like a file where all declared macros would be available in all the areas of the yaml to be reused! Including the template testing page (to test our templates with the macros).

2 Likes

That’s a cool idea. It would be great to have functions or global macros, or generic templates.

2 Likes

This would be really useful!

@petro I saw your comments on some other threads as well, e.g. Templating custom filters, RE: overriding the helpers/template.py file.

I am using a supervised installation on Debian 11, so I have HA running in a Docker container.

Is it still possible for me to make some changes to the helpers/template.py file? I found it under /usr/src/homeassistant/homeassistant/helpers/template.py in the Docker container, but I don’t know how I could modify this. Would I need to run a custom Docker image?

Or is there a way I can add custom filters/macros from code in my custom_components directory? Thanks!

I believe this is mostly the same that is requested here.

You can use the Decluttering Card to achieve this, but having it fully integrated as a helper with card preview would be really nice.

The only caveat with the Decluttering Card is that it doesn’t work across dashboards, unless you go all in on yaml dashboards (You need !include to make it work, see #43 for more info).

It’s not the same request. Jinja/template helpers(functions)/filters/macros are functions that work inside the jinja environment.

Not the same! That card is for lovelace, and this is for all JINJA

Yeah, I like this a lot. Good stepping stone to getting a full class / object (aka composites).

I’d work on this.

I do like the idea of having access to custom filters especially inline, but couldn’t this also be solved in a similar way if scripts could just have a return value as discussed here?

This would also open up for so much more things

Just want to chime in and raise awareness to how much of a requested features this (or similar) is:
https://www.google.com/search?q=home+assistant+jinja+macro

It appears Jinja fundamentally supports this through macros, include and/or import. It should be as simple as rigging up the right plumbing between Jinja and Home Assistan, in particular it seems like a loader must be defined for the Jinja environments:

{% include "test.j2" %}
TypeError: no loader for this environment specified

So it turns out this was even easier than I expected. After a bit of digging around in Home Assistant and the Jinja2 documentation, this is what I was able to cook up:

If merged, this would enable storing custom external template files in the “templates” subdirectory of your Home Assistant config directory, which could then be loaded from within templates in Home Assistant with with Jinja’s import or include statements. This allows definition of globally reusable macros in those external template files.

Note that I won’t have a bunch of time to iterate a ton on this pull request. If someone would like to take adopt it to add some tests and documentation, please feel free to do so!

3 Likes

I came here to post a link to the macros section in the Jinja docs, but it sounds like you’re beyond that at this point. Is there anything I can do to help incorporate this in HA core?

Would love to see this as there are several functions I find myself constantly referencing from other scripts/automations and would love to be able to configure them once and just call them later.

Not to mention how cool it would be to share these as easily as blueprints and crowdsource the most useful ones for official integration.

1 Like

Thank you for offering help!

Right now I have a pull request open. The pull request is awaiting review by someone on the core team. It will likely need documentation (in the form of a pull request adding the documentation to the home-assistant.io repository and some amount of automated tests added to the original pull request, to get accepted and merged into the core repository.

There’s also some uncertainty on my side if the FileSystemLoader shipping with Jinja is an acceptable venue to load source files for the Home Assistant core team. For example, I do not know if it is of concern that file IO happens as part of script execution (rather than during startup, for example). But these are things that a review would have to flag or point out.

There seems to be some objection from the HA core team. I’m going to try to see if there is any space to convincing them otherwise. I do think this is a worthwhile feature to have in Home Assistant and I think some of the objections provided previously don’t hold up to closer scrutiny. We’ll see.

1 Like

This is really a shame! This would be one great, é not one of the of the best additions to simplify a lot the yaml!

The objection is because it’s not done in a way where it will work 100% of the time. It’s not really an objection to the functionality, it’s saying that it’s implemented incorrectly.

That’s why I mentioned this above:

When I wrote the post, Paulus hadn’t explained what the main objection is yet. There were various points across all the different conversations on prior pull requests. If I understand Paulus correctly, then the main objection is that using the particular implementation in the pull request would lead to blocking file IO on the event loop, which is an obvious issue for people familiar with how event loops work.

As far as I understand Paulus, making async file IO from within rendering templates however is also not possible.

That said, I do think there’s a third option that doesn’t seem unreasonable. The macro files could be loaded together with the other configuration during startup, cached and provided to Jinja in the form of a “CachedLoader” (which internally just maps filenames to contents).

I’m not sure I have enough understanding of Home Assistant’s architecture to comment or debate on if this should be an integration loaded prior to templates or not. It’s also not clear to me how that in itself would address or fix the issue of async file IO during template rendering and I assume that you suggesting means that it is possible to hook into the template system from within an integration to provide the include / import loader implementation to the template system?

Sadly the Github pull request conversation was locked by a bot before I got the opportunity to respond. I’m following up on the Discord server to see if the conversation can be unlocked again or what the preferred medium is to continue the discussion. I do think there are possible options to get this implemented without breaking Home Assistant.

Checkout this integration.