美文网首页
Jinja宏如何接收额外参数(*args和**kwargs)?(

Jinja宏如何接收额外参数(*args和**kwargs)?(

作者: alan2yang | 来源:发表于2019-02-16 23:06 被阅读2次

    转载一篇文章,原文链接:
    如何向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元组。一般情况下,你并不需要担心这个问题。

    相关文章

      网友评论

          本文标题:Jinja宏如何接收额外参数(*args和**kwargs)?(

          本文链接:https://www.haomeiwen.com/subject/bokweqtx.html