rewrite docs, clean up typing for template decorators
This commit is contained in:
parent
daf1510a4b
commit
edebd37044
3 changed files with 229 additions and 180 deletions
|
|
@ -137,36 +137,58 @@ using in this block.
|
|||
|
||||
.. _registering-filters:
|
||||
|
||||
Registering Filters
|
||||
-------------------
|
||||
Registering Filters, Tests, and Globals
|
||||
---------------------------------------
|
||||
|
||||
If you want to register your own filters in Jinja2 you have two ways to do
|
||||
that. You can either put them by hand into the
|
||||
:attr:`~flask.Flask.jinja_env` of the application or use the
|
||||
:meth:`~flask.Flask.template_filter` decorator.
|
||||
The Flask app and blueprints provide decorators and methods to register your own
|
||||
filters, tests, and global functions for use in Jinja templates. They all follow
|
||||
the same pattern, so the following examples only discuss filters.
|
||||
|
||||
The following examples work the same and all reverse an object::
|
||||
Decorate a function with :meth:`~.Flask.template_filter` to register it as a
|
||||
template filter.
|
||||
|
||||
@app.template_filter # use the function name as filter name
|
||||
def reverse_filter(s):
|
||||
return s[::-1]
|
||||
.. code-block:: python
|
||||
|
||||
@app.template_filter('reverse')
|
||||
def reverse_filter(s):
|
||||
return s[::-1]
|
||||
@app.template_filter
|
||||
def reverse(s):
|
||||
return reversed(s)
|
||||
|
||||
def reverse_filter(s):
|
||||
return s[::-1]
|
||||
app.jinja_env.filters['reverse'] = reverse_filter
|
||||
.. code-block:: jinja
|
||||
|
||||
In case of the decorator the argument is optional if you want to use the
|
||||
function name as name of the filter. Once registered, you can use the filter
|
||||
in your templates in the same way as Jinja2's builtin filters, for example if
|
||||
you have a Python list in context called `mylist`::
|
||||
|
||||
{% for x in mylist | reverse %}
|
||||
{% for item in data | reverse %}
|
||||
{% endfor %}
|
||||
|
||||
By default it will use the name of the function as the name of the filter, but
|
||||
that can be changed by passing a name to the decorator.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.template_filter("reverse")
|
||||
def reverse_filter(s):
|
||||
return reversed(s)
|
||||
|
||||
A filter can be registered separately using :meth:`~.Flask.add_template_filter`.
|
||||
The name is optional and will use the function name if not given.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def reverse_filter(s):
|
||||
return reversed(s)
|
||||
|
||||
app.add_template_filter(reverse_filter, "reverse")
|
||||
|
||||
For template tests, use the :meth:`~.Flask.template_test` decorator or
|
||||
:meth:`~.Flask.add_template_test` method. For template global functions, use the
|
||||
:meth:`~.Flask.template_global` decorator or :meth:`~.Flask.add_template_global`
|
||||
method.
|
||||
|
||||
The same methods also exist on :class:`.Blueprint`, prefixed with ``app_`` to
|
||||
indicate that the registered functions will be avaialble to all templates, not
|
||||
only when rendering from within the blueprint.
|
||||
|
||||
The Jinja environment is also available as :attr:`~.Flask.jinja_env`. It may be
|
||||
modified directly, as you would when using Jinja outside Flask.
|
||||
|
||||
|
||||
Context Processors
|
||||
------------------
|
||||
|
|
|
|||
|
|
@ -660,37 +660,34 @@ class App(Scaffold):
|
|||
)
|
||||
self.view_functions[endpoint] = view_func
|
||||
|
||||
@t.overload
|
||||
def template_filter(self, name: T_template_filter) -> T_template_filter: ...
|
||||
@t.overload
|
||||
def template_filter(
|
||||
self, name: str | None = None
|
||||
) -> t.Callable[[T_template_filter], T_template_filter]: ...
|
||||
@setupmethod
|
||||
def template_filter(
|
||||
self, name: t.Callable[..., t.Any] | str | None = None
|
||||
) -> t.Callable[[T_template_filter], T_template_filter] | T_template_filter:
|
||||
"""A decorator that is used to register custom template filter.
|
||||
You can specify a name for the filter, otherwise the function
|
||||
name will be used. Example::
|
||||
self, name: T_template_filter | str | None = None
|
||||
) -> T_template_filter | t.Callable[[T_template_filter], T_template_filter]:
|
||||
"""Decorate a function to register it as a custom Jinja filter. The name
|
||||
is optional. The decorator may be used without parentheses.
|
||||
|
||||
@app.template_filter()
|
||||
def reverse(s):
|
||||
return s[::-1]
|
||||
.. code-block:: python
|
||||
|
||||
The decorator also can be used without parentheses::
|
||||
@app.template_filter("reverse")
|
||||
def reverse_filter(s):
|
||||
return reversed(s)
|
||||
|
||||
@app.template_filter
|
||||
def reverse(s):
|
||||
return s[::-1]
|
||||
The :meth:`add_template_filter` method may be used to register a
|
||||
function later rather than decorating.
|
||||
|
||||
:param name: the optional name of the filter, otherwise the
|
||||
function name will be used.
|
||||
:param name: The name to register the filter as. If not given, uses the
|
||||
function's name.
|
||||
"""
|
||||
|
||||
if callable(name):
|
||||
# If name is callable, it is the function to register.
|
||||
# This is a shortcut for the common case of
|
||||
# @app.template_filter
|
||||
# def func():
|
||||
|
||||
func = name
|
||||
self.add_template_filter(func)
|
||||
return func
|
||||
self.add_template_filter(name)
|
||||
return name
|
||||
|
||||
def decorator(f: T_template_filter) -> T_template_filter:
|
||||
self.add_template_filter(f, name=name)
|
||||
|
|
@ -702,24 +699,34 @@ class App(Scaffold):
|
|||
def add_template_filter(
|
||||
self, f: ft.TemplateFilterCallable, name: str | None = None
|
||||
) -> None:
|
||||
"""Register a custom template filter. Works exactly like the
|
||||
:meth:`template_filter` decorator.
|
||||
"""Register a function to use as a custom Jinja filter.
|
||||
|
||||
:param name: the optional name of the filter, otherwise the
|
||||
function name will be used.
|
||||
The :meth:`template_filter` decorator can be used to register a function
|
||||
by decorating instead.
|
||||
|
||||
:param f: The function to register.
|
||||
:param name: The name to register the filter as. If not given, uses the
|
||||
function's name.
|
||||
"""
|
||||
self.jinja_env.filters[name or f.__name__] = f
|
||||
|
||||
@t.overload
|
||||
def template_test(self, name: T_template_test) -> T_template_test: ...
|
||||
@t.overload
|
||||
def template_test(
|
||||
self, name: str | None = None
|
||||
) -> t.Callable[[T_template_test], T_template_test]: ...
|
||||
@setupmethod
|
||||
def template_test(
|
||||
self, name: t.Callable[..., t.Any] | str | None = None
|
||||
) -> t.Callable[[T_template_test], T_template_test] | T_template_filter:
|
||||
"""A decorator that is used to register custom template test.
|
||||
You can specify a name for the test, otherwise the function
|
||||
name will be used. Example::
|
||||
self, name: T_template_test | str | None = None
|
||||
) -> T_template_test | t.Callable[[T_template_test], T_template_test]:
|
||||
"""Decorate a function to register it as a custom Jinja test. The name
|
||||
is optional. The decorator may be used without parentheses.
|
||||
|
||||
@app.template_test()
|
||||
def is_prime(n):
|
||||
.. code-block:: python
|
||||
|
||||
@app.template_test("prime")
|
||||
def is_prime_test(n):
|
||||
if n == 2:
|
||||
return True
|
||||
for i in range(2, int(math.ceil(math.sqrt(n))) + 1):
|
||||
|
|
@ -727,31 +734,17 @@ class App(Scaffold):
|
|||
return False
|
||||
return True
|
||||
|
||||
The decorator also can be used without parentheses::
|
||||
The :meth:`add_template_test` method may be used to register a function
|
||||
later rather than decorating.
|
||||
|
||||
@app.template_test
|
||||
def is_prime(n):
|
||||
if n == 2:
|
||||
return True
|
||||
for i in range(2, int(math.ceil(math.sqrt(n))) + 1):
|
||||
if n % i == 0:
|
||||
return False
|
||||
:param name: The name to register the filter as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
|
||||
:param name: the optional name of the test, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
if callable(name):
|
||||
# If name is callable, it is the function to register.
|
||||
# This is a shortcut for the common case of
|
||||
# @app.template_test
|
||||
# def func():
|
||||
|
||||
func = name
|
||||
self.add_template_test(func)
|
||||
return func
|
||||
self.add_template_test(name)
|
||||
return name # type: ignore[return-value]
|
||||
|
||||
def decorator(f: T_template_test) -> T_template_test:
|
||||
self.add_template_test(f, name=name)
|
||||
|
|
@ -763,49 +756,49 @@ class App(Scaffold):
|
|||
def add_template_test(
|
||||
self, f: ft.TemplateTestCallable, name: str | None = None
|
||||
) -> None:
|
||||
"""Register a custom template test. Works exactly like the
|
||||
:meth:`template_test` decorator.
|
||||
"""Register a function to use as a custom Jinja test.
|
||||
|
||||
The :meth:`template_test` decorator can be used to register a function
|
||||
by decorating instead.
|
||||
|
||||
:param f: The function to register.
|
||||
:param name: The name to register the test as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
|
||||
:param name: the optional name of the test, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
self.jinja_env.tests[name or f.__name__] = f
|
||||
|
||||
@t.overload
|
||||
def template_global(self, name: T_template_global) -> T_template_global: ...
|
||||
@t.overload
|
||||
def template_global(
|
||||
self, name: str | None = None
|
||||
) -> t.Callable[[T_template_global], T_template_global]: ...
|
||||
@setupmethod
|
||||
def template_global(
|
||||
self, name: t.Callable[..., t.Any] | str | None = None
|
||||
) -> t.Callable[[T_template_global], T_template_global] | T_template_filter:
|
||||
"""A decorator that is used to register a custom template global function.
|
||||
You can specify a name for the global function, otherwise the function
|
||||
name will be used. Example::
|
||||
self, name: T_template_global | str | None = None
|
||||
) -> T_template_global | t.Callable[[T_template_global], T_template_global]:
|
||||
"""Decorate a function to register it as a custom Jinja global. The name
|
||||
is optional. The decorator may be used without parentheses.
|
||||
|
||||
@app.template_global()
|
||||
def double(n):
|
||||
return 2 * n
|
||||
|
||||
The decorator also can be used without parentheses::
|
||||
.. code-block:: python
|
||||
|
||||
@app.template_global
|
||||
def double(n):
|
||||
return 2 * n
|
||||
|
||||
The :meth:`add_template_global` method may be used to register a
|
||||
function later rather than decorating.
|
||||
|
||||
:param name: The name to register the global as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
|
||||
:param name: the optional name of the global function, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
if callable(name):
|
||||
# If name is callable, it is the function to register.
|
||||
# This is a shortcut for the common case of
|
||||
# @app.template_global
|
||||
# def func():
|
||||
|
||||
func = name
|
||||
self.add_template_global(func)
|
||||
return func
|
||||
self.add_template_global(name)
|
||||
return name
|
||||
|
||||
def decorator(f: T_template_global) -> T_template_global:
|
||||
self.add_template_global(f, name=name)
|
||||
|
|
@ -817,13 +810,16 @@ class App(Scaffold):
|
|||
def add_template_global(
|
||||
self, f: ft.TemplateGlobalCallable, name: str | None = None
|
||||
) -> None:
|
||||
"""Register a custom template global function. Works exactly like the
|
||||
:meth:`template_global` decorator.
|
||||
"""Register a function to use as a custom Jinja global.
|
||||
|
||||
The :meth:`template_global` decorator can be used to register a function
|
||||
by decorating instead.
|
||||
|
||||
:param f: The function to register.
|
||||
:param name: The name to register the global as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
|
||||
:param name: the optional name of the global function, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
self.jinja_env.globals[name or f.__name__] = f
|
||||
|
||||
|
|
|
|||
|
|
@ -440,26 +440,31 @@ class Blueprint(Scaffold):
|
|||
)
|
||||
)
|
||||
|
||||
@t.overload
|
||||
def app_template_filter(self, name: T_template_filter) -> T_template_filter: ...
|
||||
@t.overload
|
||||
def app_template_filter(
|
||||
self, name: str | None = None
|
||||
) -> t.Callable[[T_template_filter], T_template_filter]: ...
|
||||
@setupmethod
|
||||
def app_template_filter(
|
||||
self, name: t.Callable[..., t.Any] | str | None = None
|
||||
) -> t.Callable[[T_template_filter], T_template_filter] | T_template_filter:
|
||||
"""Register a template filter, available in any template rendered by the
|
||||
application. Equivalent to :meth:`.Flask.template_filter`.
|
||||
self, name: T_template_filter | str | None = None
|
||||
) -> T_template_filter | t.Callable[[T_template_filter], T_template_filter]:
|
||||
"""Decorate a function to register it as a custom Jinja filter. The name
|
||||
is optional. The decorator may be used without parentheses.
|
||||
|
||||
:param name: the optional name of the filter, otherwise the
|
||||
function name will be used.
|
||||
The :meth:`add_app_template_filter` method may be used to register a
|
||||
function later rather than decorating.
|
||||
|
||||
The filter is available in all templates, not only those under this
|
||||
blueprint. Equivalent to :meth:`.Flask.template_filter`.
|
||||
|
||||
:param name: The name to register the filter as. If not given, uses the
|
||||
function's name.
|
||||
"""
|
||||
|
||||
if callable(name):
|
||||
# If name is callable, it is the function to register.
|
||||
# This is a shortcut for the common case of
|
||||
# @bp.add_template_filter
|
||||
# def func():
|
||||
|
||||
func = name
|
||||
self.add_app_template_filter(func)
|
||||
return func
|
||||
self.add_app_template_filter(name)
|
||||
return name
|
||||
|
||||
def decorator(f: T_template_filter) -> T_template_filter:
|
||||
self.add_app_template_filter(f, name=name)
|
||||
|
|
@ -471,41 +476,51 @@ class Blueprint(Scaffold):
|
|||
def add_app_template_filter(
|
||||
self, f: ft.TemplateFilterCallable, name: str | None = None
|
||||
) -> None:
|
||||
"""Register a template filter, available in any template rendered by the
|
||||
application. Works like the :meth:`app_template_filter` decorator. Equivalent to
|
||||
:meth:`.Flask.add_template_filter`.
|
||||
"""Register a function to use as a custom Jinja filter.
|
||||
|
||||
:param name: the optional name of the filter, otherwise the
|
||||
function name will be used.
|
||||
The :meth:`app_template_filter` decorator can be used to register a
|
||||
function by decorating instead.
|
||||
|
||||
The filter is available in all templates, not only those under this
|
||||
blueprint. Equivalent to :meth:`.Flask.add_template_filter`.
|
||||
|
||||
:param f: The function to register.
|
||||
:param name: The name to register the filter as. If not given, uses the
|
||||
function's name.
|
||||
"""
|
||||
|
||||
def register_template(state: BlueprintSetupState) -> None:
|
||||
state.app.jinja_env.filters[name or f.__name__] = f
|
||||
def register_template_filter(state: BlueprintSetupState) -> None:
|
||||
state.app.add_template_filter(f, name=name)
|
||||
|
||||
self.record_once(register_template)
|
||||
self.record_once(register_template_filter)
|
||||
|
||||
@t.overload
|
||||
def app_template_test(self, name: T_template_test) -> T_template_test: ...
|
||||
@t.overload
|
||||
def app_template_test(
|
||||
self, name: str | None = None
|
||||
) -> t.Callable[[T_template_test], T_template_test]: ...
|
||||
@setupmethod
|
||||
def app_template_test(
|
||||
self, name: t.Callable[..., t.Any] | str | None = None
|
||||
) -> t.Callable[[T_template_test], T_template_test] | T_template_filter:
|
||||
"""Register a template test, available in any template rendered by the
|
||||
application. Equivalent to :meth:`.Flask.template_test`.
|
||||
self, name: T_template_test | str | None = None
|
||||
) -> T_template_test | t.Callable[[T_template_test], T_template_test]:
|
||||
"""Decorate a function to register it as a custom Jinja test. The name
|
||||
is optional. The decorator may be used without parentheses.
|
||||
|
||||
The :meth:`add_app_template_test` method may be used to register a
|
||||
function later rather than decorating.
|
||||
|
||||
The test is available in all templates, not only those under this
|
||||
blueprint. Equivalent to :meth:`.Flask.template_test`.
|
||||
|
||||
:param name: The name to register the filter as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
|
||||
:param name: the optional name of the test, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
if callable(name):
|
||||
# If name is callable, it is the function to register.
|
||||
# This is a shortcut for the common case of
|
||||
# @bp.add_template_test
|
||||
# def func():
|
||||
|
||||
func = name
|
||||
self.add_app_template_test(func)
|
||||
return func
|
||||
self.add_app_template_test(name)
|
||||
return name # type: ignore[return-value]
|
||||
|
||||
def decorator(f: T_template_test) -> T_template_test:
|
||||
self.add_app_template_test(f, name=name)
|
||||
|
|
@ -517,42 +532,53 @@ class Blueprint(Scaffold):
|
|||
def add_app_template_test(
|
||||
self, f: ft.TemplateTestCallable, name: str | None = None
|
||||
) -> None:
|
||||
"""Register a template test, available in any template rendered by the
|
||||
application. Works like the :meth:`app_template_test` decorator. Equivalent to
|
||||
:meth:`.Flask.add_template_test`.
|
||||
"""Register a function to use as a custom Jinja test.
|
||||
|
||||
The :meth:`app_template_test` decorator can be used to register a
|
||||
function by decorating instead.
|
||||
|
||||
The test is available in all templates, not only those under this
|
||||
blueprint. Equivalent to :meth:`.Flask.add_template_test`.
|
||||
|
||||
:param f: The function to register.
|
||||
:param name: The name to register the test as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
|
||||
:param name: the optional name of the test, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
def register_template(state: BlueprintSetupState) -> None:
|
||||
state.app.jinja_env.tests[name or f.__name__] = f
|
||||
def register_template_test(state: BlueprintSetupState) -> None:
|
||||
state.app.add_template_test(f, name=name)
|
||||
|
||||
self.record_once(register_template)
|
||||
self.record_once(register_template_test)
|
||||
|
||||
@t.overload
|
||||
def app_template_global(self, name: T_template_global) -> T_template_global: ...
|
||||
@t.overload
|
||||
def app_template_global(
|
||||
self, name: str | None = None
|
||||
) -> t.Callable[[T_template_global], T_template_global]: ...
|
||||
@setupmethod
|
||||
def app_template_global(
|
||||
self, name: t.Callable[..., t.Any] | str | None = None
|
||||
) -> t.Callable[[T_template_global], T_template_global] | T_template_filter:
|
||||
"""Register a template global, available in any template rendered by the
|
||||
application. Equivalent to :meth:`.Flask.template_global`.
|
||||
self, name: T_template_global | str | None = None
|
||||
) -> T_template_global | t.Callable[[T_template_global], T_template_global]:
|
||||
"""Decorate a function to register it as a custom Jinja global. The name
|
||||
is optional. The decorator may be used without parentheses.
|
||||
|
||||
The :meth:`add_app_template_global` method may be used to register a
|
||||
function later rather than decorating.
|
||||
|
||||
The global is available in all templates, not only those under this
|
||||
blueprint. Equivalent to :meth:`.Flask.template_global`.
|
||||
|
||||
:param name: The name to register the global as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
|
||||
:param name: the optional name of the global, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
if callable(name):
|
||||
# If name is callable, it is the function to register.
|
||||
# This is a shortcut for the common case of
|
||||
# @bp.add_template_global
|
||||
# def func():
|
||||
|
||||
func = name
|
||||
self.add_app_template_global(func)
|
||||
return func
|
||||
self.add_app_template_global(name)
|
||||
return name
|
||||
|
||||
def decorator(f: T_template_global) -> T_template_global:
|
||||
self.add_app_template_global(f, name=name)
|
||||
|
|
@ -564,20 +590,25 @@ class Blueprint(Scaffold):
|
|||
def add_app_template_global(
|
||||
self, f: ft.TemplateGlobalCallable, name: str | None = None
|
||||
) -> None:
|
||||
"""Register a template global, available in any template rendered by the
|
||||
application. Works like the :meth:`app_template_global` decorator. Equivalent to
|
||||
:meth:`.Flask.add_template_global`.
|
||||
"""Register a function to use as a custom Jinja global.
|
||||
|
||||
The :meth:`app_template_global` decorator can be used to register a function
|
||||
by decorating instead.
|
||||
|
||||
The global is available in all templates, not only those under this
|
||||
blueprint. Equivalent to :meth:`.Flask.add_template_global`.
|
||||
|
||||
:param f: The function to register.
|
||||
:param name: The name to register the global as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
|
||||
:param name: the optional name of the global, otherwise the
|
||||
function name will be used.
|
||||
"""
|
||||
|
||||
def register_template(state: BlueprintSetupState) -> None:
|
||||
state.app.jinja_env.globals[name or f.__name__] = f
|
||||
def register_template_global(state: BlueprintSetupState) -> None:
|
||||
state.app.add_template_global(f, name=name)
|
||||
|
||||
self.record_once(register_template)
|
||||
self.record_once(register_template_global)
|
||||
|
||||
@setupmethod
|
||||
def before_app_request(self, f: T_before_request) -> T_before_request:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue