support call template_filter without parens (#5736)
This commit is contained in:
commit
ed1c9e953e
6 changed files with 410 additions and 112 deletions
|
|
@ -5,6 +5,8 @@ Unreleased
|
|||
|
||||
- Drop support for Python 3.9. :pr:`5730`
|
||||
- Remove previously deprecated code: ``__version__``. :pr:`5648`
|
||||
- ``template_filter``, ``template_test``, and ``template_global`` decorators
|
||||
can be used without parentheses. :issue:`5729`
|
||||
|
||||
|
||||
Version 3.1.1
|
||||
|
|
|
|||
|
|
@ -137,32 +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 two following examples work the same and both reverse an object::
|
||||
Decorate a function with :meth:`~.Flask.template_filter` to register it as a
|
||||
template filter.
|
||||
|
||||
@app.template_filter('reverse')
|
||||
def reverse_filter(s):
|
||||
return s[::-1]
|
||||
.. code-block:: python
|
||||
|
||||
def reverse_filter(s):
|
||||
return s[::-1]
|
||||
app.jinja_env.filters['reverse'] = reverse_filter
|
||||
@app.template_filter
|
||||
def reverse(s):
|
||||
return reversed(s)
|
||||
|
||||
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`::
|
||||
.. code-block:: jinja
|
||||
|
||||
{% 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,21 +660,34 @@ class App(Scaffold):
|
|||
)
|
||||
self.view_functions[endpoint] = view_func
|
||||
|
||||
@setupmethod
|
||||
@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]:
|
||||
"""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::
|
||||
) -> t.Callable[[T_template_filter], T_template_filter]: ...
|
||||
@setupmethod
|
||||
def 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.
|
||||
|
||||
@app.template_filter()
|
||||
def reverse(s):
|
||||
return s[::-1]
|
||||
.. code-block:: python
|
||||
|
||||
:param name: the optional name of the filter, otherwise the
|
||||
function name will be used.
|
||||
@app.template_filter("reverse")
|
||||
def reverse_filter(s):
|
||||
return reversed(s)
|
||||
|
||||
The :meth:`add_template_filter` method may be used to register a
|
||||
function later rather than decorating.
|
||||
|
||||
:param name: The name to register the filter as. If not given, uses the
|
||||
function's name.
|
||||
"""
|
||||
if callable(name):
|
||||
self.add_template_filter(name)
|
||||
return name
|
||||
|
||||
def decorator(f: T_template_filter) -> T_template_filter:
|
||||
self.add_template_filter(f, name=name)
|
||||
|
|
@ -686,36 +699,52 @@ 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
|
||||
|
||||
@setupmethod
|
||||
@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]:
|
||||
"""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::
|
||||
) -> t.Callable[[T_template_test], T_template_test]: ...
|
||||
@setupmethod
|
||||
def 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.
|
||||
|
||||
@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
|
||||
.. 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):
|
||||
if n % i == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
.. versionadded:: 0.10
|
||||
The :meth:`add_template_test` method may be used to register a function
|
||||
later rather than decorating.
|
||||
|
||||
:param name: the optional name of the test, otherwise the
|
||||
function name will be used.
|
||||
:param name: The name to register the filter as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
"""
|
||||
if callable(name):
|
||||
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)
|
||||
|
|
@ -727,33 +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
|
||||
|
||||
@setupmethod
|
||||
@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]:
|
||||
"""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::
|
||||
) -> t.Callable[[T_template_global], T_template_global]: ...
|
||||
@setupmethod
|
||||
def 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.
|
||||
|
||||
@app.template_global()
|
||||
.. code-block:: python
|
||||
|
||||
@app.template_global
|
||||
def double(n):
|
||||
return 2 * n
|
||||
|
||||
.. versionadded:: 0.10
|
||||
The :meth:`add_template_global` method may be used to register a
|
||||
function later rather than decorating.
|
||||
|
||||
:param name: the optional name of the global function, otherwise the
|
||||
function name will be used.
|
||||
:param name: The name to register the global as. If not given, uses the
|
||||
function's name.
|
||||
|
||||
.. versionadded:: 0.10
|
||||
"""
|
||||
if callable(name):
|
||||
self.add_template_global(name)
|
||||
return name
|
||||
|
||||
def decorator(f: T_template_global) -> T_template_global:
|
||||
self.add_template_global(f, name=name)
|
||||
|
|
@ -765,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,16 +440,31 @@ class Blueprint(Scaffold):
|
|||
)
|
||||
)
|
||||
|
||||
@setupmethod
|
||||
@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]:
|
||||
"""Register a template filter, available in any template rendered by the
|
||||
application. Equivalent to :meth:`.Flask.template_filter`.
|
||||
) -> t.Callable[[T_template_filter], T_template_filter]: ...
|
||||
@setupmethod
|
||||
def app_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):
|
||||
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)
|
||||
|
|
@ -461,31 +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)
|
||||
|
||||
@setupmethod
|
||||
@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]:
|
||||
"""Register a template test, available in any template rendered by the
|
||||
application. Equivalent to :meth:`.Flask.template_test`.
|
||||
) -> t.Callable[[T_template_test], T_template_test]: ...
|
||||
@setupmethod
|
||||
def app_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):
|
||||
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)
|
||||
|
|
@ -497,33 +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)
|
||||
|
||||
@setupmethod
|
||||
@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]:
|
||||
"""Register a template global, available in any template rendered by the
|
||||
application. Equivalent to :meth:`.Flask.template_global`.
|
||||
) -> t.Callable[[T_template_global], T_template_global]: ...
|
||||
@setupmethod
|
||||
def app_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):
|
||||
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)
|
||||
|
|
@ -535,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:
|
||||
|
|
|
|||
|
|
@ -366,11 +366,35 @@ def test_template_filter(app):
|
|||
def my_reverse(s):
|
||||
return s[::-1]
|
||||
|
||||
@bp.app_template_filter
|
||||
def my_reverse_2(s):
|
||||
return s[::-1]
|
||||
|
||||
@bp.app_template_filter("my_reverse_custom_name_3")
|
||||
def my_reverse_3(s):
|
||||
return s[::-1]
|
||||
|
||||
@bp.app_template_filter(name="my_reverse_custom_name_4")
|
||||
def my_reverse_4(s):
|
||||
return s[::-1]
|
||||
|
||||
app.register_blueprint(bp, url_prefix="/py")
|
||||
assert "my_reverse" in app.jinja_env.filters.keys()
|
||||
assert app.jinja_env.filters["my_reverse"] == my_reverse
|
||||
assert app.jinja_env.filters["my_reverse"]("abcd") == "dcba"
|
||||
|
||||
assert "my_reverse_2" in app.jinja_env.filters.keys()
|
||||
assert app.jinja_env.filters["my_reverse_2"] == my_reverse_2
|
||||
assert app.jinja_env.filters["my_reverse_2"]("abcd") == "dcba"
|
||||
|
||||
assert "my_reverse_custom_name_3" in app.jinja_env.filters.keys()
|
||||
assert app.jinja_env.filters["my_reverse_custom_name_3"] == my_reverse_3
|
||||
assert app.jinja_env.filters["my_reverse_custom_name_3"]("abcd") == "dcba"
|
||||
|
||||
assert "my_reverse_custom_name_4" in app.jinja_env.filters.keys()
|
||||
assert app.jinja_env.filters["my_reverse_custom_name_4"] == my_reverse_4
|
||||
assert app.jinja_env.filters["my_reverse_custom_name_4"]("abcd") == "dcba"
|
||||
|
||||
|
||||
def test_add_template_filter(app):
|
||||
bp = flask.Blueprint("bp", __name__)
|
||||
|
|
@ -502,11 +526,35 @@ def test_template_test(app):
|
|||
def is_boolean(value):
|
||||
return isinstance(value, bool)
|
||||
|
||||
@bp.app_template_test
|
||||
def boolean_2(value):
|
||||
return isinstance(value, bool)
|
||||
|
||||
@bp.app_template_test("my_boolean_custom_name")
|
||||
def boolean_3(value):
|
||||
return isinstance(value, bool)
|
||||
|
||||
@bp.app_template_test(name="my_boolean_custom_name_2")
|
||||
def boolean_4(value):
|
||||
return isinstance(value, bool)
|
||||
|
||||
app.register_blueprint(bp, url_prefix="/py")
|
||||
assert "is_boolean" in app.jinja_env.tests.keys()
|
||||
assert app.jinja_env.tests["is_boolean"] == is_boolean
|
||||
assert app.jinja_env.tests["is_boolean"](False)
|
||||
|
||||
assert "boolean_2" in app.jinja_env.tests.keys()
|
||||
assert app.jinja_env.tests["boolean_2"] == boolean_2
|
||||
assert app.jinja_env.tests["boolean_2"](False)
|
||||
|
||||
assert "my_boolean_custom_name" in app.jinja_env.tests.keys()
|
||||
assert app.jinja_env.tests["my_boolean_custom_name"] == boolean_3
|
||||
assert app.jinja_env.tests["my_boolean_custom_name"](False)
|
||||
|
||||
assert "my_boolean_custom_name_2" in app.jinja_env.tests.keys()
|
||||
assert app.jinja_env.tests["my_boolean_custom_name_2"] == boolean_4
|
||||
assert app.jinja_env.tests["my_boolean_custom_name_2"](False)
|
||||
|
||||
|
||||
def test_add_template_test(app):
|
||||
bp = flask.Blueprint("bp", __name__)
|
||||
|
|
@ -679,6 +727,18 @@ def test_template_global(app):
|
|||
def get_answer():
|
||||
return 42
|
||||
|
||||
@bp.app_template_global
|
||||
def get_stuff_1():
|
||||
return "get_stuff_1"
|
||||
|
||||
@bp.app_template_global("my_get_stuff_custom_name_2")
|
||||
def get_stuff_2():
|
||||
return "get_stuff_2"
|
||||
|
||||
@bp.app_template_global(name="my_get_stuff_custom_name_3")
|
||||
def get_stuff_3():
|
||||
return "get_stuff_3"
|
||||
|
||||
# Make sure the function is not in the jinja_env already
|
||||
assert "get_answer" not in app.jinja_env.globals.keys()
|
||||
app.register_blueprint(bp)
|
||||
|
|
@ -688,10 +748,31 @@ def test_template_global(app):
|
|||
assert app.jinja_env.globals["get_answer"] is get_answer
|
||||
assert app.jinja_env.globals["get_answer"]() == 42
|
||||
|
||||
assert "get_stuff_1" in app.jinja_env.globals.keys()
|
||||
assert app.jinja_env.globals["get_stuff_1"] == get_stuff_1
|
||||
assert app.jinja_env.globals["get_stuff_1"](), "get_stuff_1"
|
||||
|
||||
assert "my_get_stuff_custom_name_2" in app.jinja_env.globals.keys()
|
||||
assert app.jinja_env.globals["my_get_stuff_custom_name_2"] == get_stuff_2
|
||||
assert app.jinja_env.globals["my_get_stuff_custom_name_2"](), "get_stuff_2"
|
||||
|
||||
assert "my_get_stuff_custom_name_3" in app.jinja_env.globals.keys()
|
||||
assert app.jinja_env.globals["my_get_stuff_custom_name_3"] == get_stuff_3
|
||||
assert app.jinja_env.globals["my_get_stuff_custom_name_3"](), "get_stuff_3"
|
||||
|
||||
with app.app_context():
|
||||
rv = flask.render_template_string("{{ get_answer() }}")
|
||||
assert rv == "42"
|
||||
|
||||
rv = flask.render_template_string("{{ get_stuff_1() }}")
|
||||
assert rv == "get_stuff_1"
|
||||
|
||||
rv = flask.render_template_string("{{ my_get_stuff_custom_name_2() }}")
|
||||
assert rv == "get_stuff_2"
|
||||
|
||||
rv = flask.render_template_string("{{ my_get_stuff_custom_name_3() }}")
|
||||
assert rv == "get_stuff_3"
|
||||
|
||||
|
||||
def test_request_processing(app, client):
|
||||
bp = flask.Blueprint("bp", __name__)
|
||||
|
|
|
|||
|
|
@ -129,6 +129,30 @@ def test_template_filter(app):
|
|||
assert app.jinja_env.filters["my_reverse"] == my_reverse
|
||||
assert app.jinja_env.filters["my_reverse"]("abcd") == "dcba"
|
||||
|
||||
@app.template_filter
|
||||
def my_reverse_2(s):
|
||||
return s[::-1]
|
||||
|
||||
assert "my_reverse_2" in app.jinja_env.filters.keys()
|
||||
assert app.jinja_env.filters["my_reverse_2"] == my_reverse_2
|
||||
assert app.jinja_env.filters["my_reverse_2"]("abcd") == "dcba"
|
||||
|
||||
@app.template_filter("my_reverse_custom_name_3")
|
||||
def my_reverse_3(s):
|
||||
return s[::-1]
|
||||
|
||||
assert "my_reverse_custom_name_3" in app.jinja_env.filters.keys()
|
||||
assert app.jinja_env.filters["my_reverse_custom_name_3"] == my_reverse_3
|
||||
assert app.jinja_env.filters["my_reverse_custom_name_3"]("abcd") == "dcba"
|
||||
|
||||
@app.template_filter(name="my_reverse_custom_name_4")
|
||||
def my_reverse_4(s):
|
||||
return s[::-1]
|
||||
|
||||
assert "my_reverse_custom_name_4" in app.jinja_env.filters.keys()
|
||||
assert app.jinja_env.filters["my_reverse_custom_name_4"] == my_reverse_4
|
||||
assert app.jinja_env.filters["my_reverse_custom_name_4"]("abcd") == "dcba"
|
||||
|
||||
|
||||
def test_add_template_filter(app):
|
||||
def my_reverse(s):
|
||||
|
|
@ -223,6 +247,30 @@ def test_template_test(app):
|
|||
assert app.jinja_env.tests["boolean"] == boolean
|
||||
assert app.jinja_env.tests["boolean"](False)
|
||||
|
||||
@app.template_test
|
||||
def boolean_2(value):
|
||||
return isinstance(value, bool)
|
||||
|
||||
assert "boolean_2" in app.jinja_env.tests.keys()
|
||||
assert app.jinja_env.tests["boolean_2"] == boolean_2
|
||||
assert app.jinja_env.tests["boolean_2"](False)
|
||||
|
||||
@app.template_test("my_boolean_custom_name")
|
||||
def boolean_3(value):
|
||||
return isinstance(value, bool)
|
||||
|
||||
assert "my_boolean_custom_name" in app.jinja_env.tests.keys()
|
||||
assert app.jinja_env.tests["my_boolean_custom_name"] == boolean_3
|
||||
assert app.jinja_env.tests["my_boolean_custom_name"](False)
|
||||
|
||||
@app.template_test(name="my_boolean_custom_name_2")
|
||||
def boolean_4(value):
|
||||
return isinstance(value, bool)
|
||||
|
||||
assert "my_boolean_custom_name_2" in app.jinja_env.tests.keys()
|
||||
assert app.jinja_env.tests["my_boolean_custom_name_2"] == boolean_4
|
||||
assert app.jinja_env.tests["my_boolean_custom_name_2"](False)
|
||||
|
||||
|
||||
def test_add_template_test(app):
|
||||
def boolean(value):
|
||||
|
|
@ -320,6 +368,39 @@ def test_add_template_global(app, app_ctx):
|
|||
rv = flask.render_template_string("{{ get_stuff() }}")
|
||||
assert rv == "42"
|
||||
|
||||
@app.template_global
|
||||
def get_stuff_1():
|
||||
return "get_stuff_1"
|
||||
|
||||
assert "get_stuff_1" in app.jinja_env.globals.keys()
|
||||
assert app.jinja_env.globals["get_stuff_1"] == get_stuff_1
|
||||
assert app.jinja_env.globals["get_stuff_1"](), "get_stuff_1"
|
||||
|
||||
rv = flask.render_template_string("{{ get_stuff_1() }}")
|
||||
assert rv == "get_stuff_1"
|
||||
|
||||
@app.template_global("my_get_stuff_custom_name_2")
|
||||
def get_stuff_2():
|
||||
return "get_stuff_2"
|
||||
|
||||
assert "my_get_stuff_custom_name_2" in app.jinja_env.globals.keys()
|
||||
assert app.jinja_env.globals["my_get_stuff_custom_name_2"] == get_stuff_2
|
||||
assert app.jinja_env.globals["my_get_stuff_custom_name_2"](), "get_stuff_2"
|
||||
|
||||
rv = flask.render_template_string("{{ my_get_stuff_custom_name_2() }}")
|
||||
assert rv == "get_stuff_2"
|
||||
|
||||
@app.template_global(name="my_get_stuff_custom_name_3")
|
||||
def get_stuff_3():
|
||||
return "get_stuff_3"
|
||||
|
||||
assert "my_get_stuff_custom_name_3" in app.jinja_env.globals.keys()
|
||||
assert app.jinja_env.globals["my_get_stuff_custom_name_3"] == get_stuff_3
|
||||
assert app.jinja_env.globals["my_get_stuff_custom_name_3"](), "get_stuff_3"
|
||||
|
||||
rv = flask.render_template_string("{{ my_get_stuff_custom_name_3() }}")
|
||||
assert rv == "get_stuff_3"
|
||||
|
||||
|
||||
def test_custom_template_loader(client):
|
||||
class MyFlask(flask.Flask):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue