Description
What's the issue?
You can use template_filter
as a decorator, but it only registers the filter if you write an explicit name or an empty set of parentheses. If you call it without parens, the filter doesn't get registered.
It's a small difference and can be confusing.
Minimal example
Consider the following program:
from flask import Flask, render_template_string
app = Flask(__name__)
@app.template_filter
def double(x):
return x * 2
@app.route("/")
def index():
return render_template_string("2 times 2 is {{ 2 | double }}")
If you run this app (flask run --port 8008 --debug
) and then open it in your browser (http://localhost:8008
) you'll get an error:
jinja2.exceptions.TemplateAssertionError: No filter named 'double'.
This is confusing, and it took me a while to realise the missing parentheses in app.template_filter
were at fault.
Suggested fix
I think it would be helpful if the decorator either:
- Supported being called without parentheses, or
- Printed an explicit warning if called this way, e.g.
Did you use 'template_filter' as a decorator without parentheses? You need to call it with 'template_filter()'
This is caught by type checkers, but not everybody type checks their Python and the error message is less obvious:
Argument 1 to "template_filter" of "App" has incompatible type "Callable[[Any], Any]"; expected "str | None"
I've had a look at the relevant code, and I'd be happy to provide a patch if you think this is a useful change.
Environment
- Python version: Python 3.11.11
- Flask version: Flask 3.1.0