Skip to content

optionally use a filter based on its existence #842

@nixjdm

Description

@nixjdm

I propose a feature, where within a template, you can test for the existence of a filter so that you can then use that filter if it exists, and not if it doesn't.

For example,

{% if filter is callable %}
  {{ var|filter }}
{% else %}
  {{ var }} {# no use of 'filter' #}
{% endif %}

Currently, if the filter does not exist, Jinja would throw a jinja2.exceptions.TemplateAssertionError: no filter named 'filter' because of the line {{ var|filter }}. The desired output is what is rendered in the else. You can test if the filter is callable, but you cannot then optionally use it. At a high level this is similar to how one might commonly use a var, if it exists.

{% if myvar is defined %}
  {{ myvar }}
{% else %}
  No myvar {# no use of 'myvar' #}
{% endif %}

Example Use Case:

I would like to be able to write Lektor themes such that they can take advantage of filters provided by various Lektor plugins if they are installed. I do not want to require those plugins, and thus also their provided filters. I'd want a Lektor theme to flexibly handle either situation, as per the users' desire.

More generally, Jinja templates in any Flask or Django project could be written more flexibly to handle the optional presence filters. Adding custom or 3rd party filters is a common thing to do. Passing templates around between projects would be easier if they didn't force implementation of custom filters.

Implementation:

The desired effect could be achieved more than one way. For example, at least

  1. not raising an exception when evaluating {{ var|filter }} and instead returning (basically anything) would allow the above snippet to be rendered.

  2. change the way the entire if is evaluated, such that the expressions contained in the contents of the "true" section are evaluated only if the test passes. Evaluation would resume upon reaching an else or endif.

My intuition was that the second option was already happening, but it is not. Though the contents of the passing section of the if never get to the final rendered product, the expressions are still evaluated anyway. Otherwise no exception would be rendered. If 2. happened, that could mean much nonsense could be included in between the if and the else, and not trip exceptions. That sounds like a change that's worth some careful thought, but I can't immediately think of a problem with it. I am not intimately familiar with Jinja's internals. Exceptions would still be raised if the test ever actually passes.
Skipping that section may also mean performance improvements, which is a nice side effect.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions