8

如何向Jinja宏传递额外参数(*args和**kwargs)?

 3 years ago
source link: https://greyli.com/use-kwargs-args-in-jinja-macro/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

如何向Jinja宏传递额外参数(*args和**kwargs)?

这段时间有多个读者问关于Jinja宏定义时的参数接受问题。这一点在《Flask Web开发实战》里没有介绍,这篇文章作为一个补充。

一个不符合直觉的设定

在某个晴朗的早晨,你打开电脑,想在你的项目Jinja模板里编写一个宏来简化操作。按照直觉,你可能会像定义Python函数那样来定义宏,传入**kwargs来让它接收任意数量的关键字参数,比如:

{% macro say_hello(**kwargs) %}
{% endmacro %}

或是传入*args让它接收任意数量的位置参数:

{% macro say_hello(*args) %}
{% endmacro %}

遗憾的是,上面的调用会分别获得下面的错误信息:

jinja2.exceptions.TemplateSyntaxError: expected token 'name', got '**'
jinja2.exceptions.TemplateSyntaxError: expected token 'name', got '*'

在Jinja宏里接收额外的关键字参数和位置参数

在Jinja中,宏默认会自动接收额外的关键字参数和位置参数,并在宏内部提供kwargsvarargs特殊变量来获取它们。具体来说,在定义宏的时候,不需要进行任何声明。在宏的内部,你可以直接使用kwargs字典来获取额外的关键字参数;同样的,你可以使用varargs元组来获取额外传入的位置参数。

下面是使用kwargs的示例:

{% macro say_hello() %}
    <p>Hello, {{ kwargs['name'] }}!</p>
{% endmacro %}
{# 调用示例 #}
{{ say_hello(name='Grey')}}

你可以把这个字典传递给其他函数,比如url_for():

{% macro nav_link(endpoint, text) %}
    <a href="{{ url_for(endpoint, **kwargs) }}">{{ text }}</a>
{% endmacro %}
{# 调用示例 #}
{{ nav_link('index', 'Home', foo='value1', bar='value2')}}

下面是使用varargs的示例:

{% macro say_hello() %}
    <p>Hello, {{ varargs[0] }}!</p>
{% endmacro %}
{# 调用示例 #}
{{ say_hello('Grey')}}

提示 在宏内部,如果kwargs字典里没有对应的键,那么会返回空字符串,而不是抛出KeyError异常;如果向varargs元组索引一个超出范围的下标值,也会返回空值,而不会抛出IndexError异常。

隐藏的陷阱

虽然宏自动处理额外传入的关键字参数和位置参数,但是这里有一个隐藏的小陷阱。如果你在调用一个宏的时候传入了额外的关键字参数和位置参数,但是宏的内部并没有使用它们,这时就会出错。比如下面使用kwargs的示例:

{% macro say_hello() %}
    <p>Hello!</p>
{% endmacro %}
{# 调用示例 #}
{{ say_hello(name='Grey')}}

调用宏的时候传入了name参数,但是宏内部并没有使用它,这时Jinja会抛出下面的异常:

TypeError: macro 'say_hello' takes no keyword argument 'name'

类似的是位置参数,你会获得下面的异常:

TypeError: macro 'say_hello' takes not more than 1 argument(s)

所以,如果你想让某个宏接收额外的关键字参数或位置参数,你就分别需要在这个宏内部至少调用一次(access)kwargs字典或是varargs元组。一般情况下,你并不需要担心这个问题。

本文隶属于《Flask Web开发实战》番外文章系列。

本条目发布于2018年10月22日。属于计算机与编程分类,被贴了 FlaskFlask Web开发实战Jinja 标签。 ← Pipenv使用时出现TypeError、ResourceWarning、或ImportError错误的解决方法 参加北京 PyCon China 2018 →

撰写评论 取消回复

电子邮件地址不会被公开,必填项已用*标出。

评论

姓名 *

电子邮件 *

站点

在此浏览器中保存我的名字、电邮和网站。

当有人回复我时,发送电子邮件提醒我。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK