zoukankan      html  css  js  c++  java
  • Flask-宏的相关知识。

    转自ITOYO:XIAOJINGJING

    Jinja2的宏功能有些类似于传统程序语言中的函数,既然是函数就有其声明和调用两个部分。

    首先声明一个宏:

     1 <html lang="en">  
     2 <head>  
     3     <meta charset="UTF-8">  
     4     <title>Title</title>  
     5 </head>  
     6 <body>  
     7 {% macro input(name,type='text',value='') %}  
     8     <input type="{{ type }}" name="{{ name }}" value="{{ value }}">  
     9 {% endmacro %}  
    10 {#代码中,宏的名称就是”input”,它有三个参数分别是”name”, “type”和”value”,后两个参数有默认值。#}  
    11 </body>  
    12 </html>  

    代码中,宏的名称就是”input”,它有三个参数分别是”name”, “type”和”value”,后两个参数有默认值。现在,让我们使用表达式来调用这个宏:

    在上面代码中加入如下代码:

    1 <p>{{ input('username',value='user') }}</p>  
    2 <p>{{ input('password','password') }}</p>  
    3 <p>{{ input('submit','submit','submit') }}</p>  

    定义路由,把页面配置进入路由后,访问在页面上看到一个文本输入框,一个密码输入框及一个提交按钮。

    宏的复用:

    1 {% from "macro.html" import input %} 

    引用需要复用的宏文件macro.html,然后调用宏内容,代码如下:

     1 <html lang="en">  
     2 <head>  
     3     <meta charset="UTF-8">  
     4     <title>Title</title>  
     5 </head>  
     6 <body>  
     7 {% from "macro.html" import input %}  
     8 <p>{{ input('username',value='user') }}</p>  
     9 <p>{{ input('password','password') }}</p>  
    10 <p>{{ input('submit','submit','submit') }}</p>  
    11 </body>  
    12 </html>  

    访问调用者内容

    我们先创建一个macrouser_list.html文件,代码如下:

     1 <html lang="en">  
     2 <head>  
     3     <meta charset="UTF-8">  
     4     <title>Title</title>  
     5 </head>  
     6 <body>  
     7 {% macro user_list(users) %}  
     8     <table>  
     9     <tr><th>Name</th><th>Sex</th><th>Age</th><th>Action</th></tr>  
    10     {% for user in users %}  
    11         <tr><td>{{ user.name  }}</td><td>{{ user.gender }}</td><td>{{ user.age }}</td><td>{{ caller() }}</td></tr>  
    12     {% endfor %}  
    13     </table>  
    14 {% endmacro %}  
    15 </body>  
    16 </html>  

    我们还是在usemacro.html文件中设置调用者内容,代码如下:

     1 {% from "macrouser_list.html" import user_list %}  
     2   
     3 {% set users=[{'name':'Tom','gender':'Boy','age':'26'},  
     4 {'name':'Jim','gender':'Boy','age':'25'},  
     5 {'name':'Lucy','gender':'Girl','age':'23'},  
     6 {'name':'Lida','gender':'Girl','age':'22'}]  
     7         %}  
     8 _______________________________________________________________  
     9 {% call user_list(users) %}  
    10 {% endcall %}  
    11 ________________________________________________________________  
    12 {% call user_list(users) %}  
    13  <input name="delete" type="delete" value="delete">  
    14 {% endcall %}  
    15   
    16   
    17 ____________________________________________________________  
    18 {% for user in users %}  
    19         <tr><td>{{ user.name }}</td><td>{{ user.gender }}</td><td>{{ user.age }}</td><td><input name="delete" type="delete" value="delete"></td></tr>  
    20     {% endfor %}  

    访问:http://127.0.0.1:5000/usemacro,可以看到结果。

    与上例不同,这里我们使用了”{% call %}”语句块来调用宏,语句块中包括了一段生成”Delete”按钮的代码。运行下试试,你会发现每个用户名后面都出现了”Delete”按钮,也就是”{{ caller( ) }}”部分被调用者”{% call %}”语句块内部的内容替代了。不明觉厉吧!其实吧,这个跟函数传个参数进去没啥大区别,个人觉得,主要是有些时候HTML语句太复杂(如上例),不方便写在调用参数上,所以就写在”{% call %}”语句块里了。

    Jinja2的宏不但能访问调用者语句块的内容,还能给调用者传递参数。们来扩展下上面的例子。首先,我们将表格增加一列性别,并在宏里调用”caller()”方法时,传入一个变量”user.gender”:

    1 {% macro list_users(users) -%}  
    2   <table>  
    3     <tr><th>Name</th><th>Gender</th><th>Action</th></tr>  
    4     {%- for user in users %}  
    5       <tr><td>{{ user.name |e }}</td>{{ caller(user.gender) }}</tr>  
    6     {%- endfor %}  
    7   </table>  
    8 {%- endmacro %}  

    然后,我们修改下调用者语句块:

     1 {% call(gender) list_users(users) %}  
     2     <td>  
     3     {% if gender == 'M' %}  
     4     <img src="{{ url_for('static', filename='img/male.png') }}" width="20px">  
     5     {% else %}  
     6     <img src="{{ url_for('static', filename='img/female.png') }}" width="20px">  
     7     {% endif %}  
     8     </td>  
     9     <td><input name="delete" type="button" value="Delete"></td>  
    10 {% endcall %}  

    大家注意到,我们在使用”{% call %}”语句时,将其改为了”{% call(gender) … %}”,这个括号中的”gender”就是用来接受宏里传来的”user.gender”变量。因此我们就可以在”{% call %}”语句中使用这个”gender”变量来判断用户性别。这样宏就成功地向调用者传递了参数。

    宏的内部变量

    上例中,我们看到宏的内部可以使用”caller( )”方法获取调用者的内容。此外宏还提供了两个内部变量:

      • varargs

    这是一个列表。如果调用宏时传入的参数多于宏声明时的参数,多出来的没指定参数名的参数就会保存在这个列表中。

      • kwargs

    这是一个字典。如果调用宏时传入的参数多于宏声明时的参数,多出来的指定了参数名的参数就会保存在这个字典中。

    让我们回到第一个例子input宏,在调用时增加其传入的参数,并在宏内将上述两个变量打印出来:

    1 {% macro input(name, type='text', value='') -%}  
    2     <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}">  
    3     <br /> {{ varargs }}  
    4     <br /> {{ kwargs }}  
    5 {%- endmacro %}  
    6 <p>{{ input('submit', 'submit', 'Submit', 'more arg1', 'more arg2', ext='more arg3') }}</p> 

     可以看到,varargs变量存了参数列表”[‘more arg1’, ‘more arg2’]”,而kwargs字典存了参数”{‘ext’:’more arg3′}”。

    宏的导入

    一个宏可以被不同的模板使用,所以我们建议将其声明在一个单独的模板文件中。需要使用时导入进来即可,而导入的方法也非常类似于Python中的”import”。让我们将第一个例子中”input”宏的声明放到一个”form.html”模板文件中,然后将调用的代码改为:

    1 {% import 'form.html' as form %}  
    2 <p>{{ form.input('username', value='user') }}</p>  
    3 <p>{{ form.input('password', 'password') }}</p>  
    4 <p>{{ form.input('submit', 'submit', 'Submit') }}</p>  
    包含 (Include)

    这里我们再介绍一个Jinja2模板中代码重用的功能,就是包含 (Include),使用的方法就是”{% include %}”语句。其功能就是将另一个模板加载到当前模板中,并直接渲染在当前位置上。它同导入”import”不一样,”import”之后你还需要调用宏来渲染你的内容,”include”是直接将目标模板渲染出来。它同block块继承也不一样,它一次渲染整个模板文件内容,不分块。

    我们可以创建一个”footer.html”模板,并在”layout.html”中包含这个模板:

    1 <body>  
    2     ...  
    3     {% include 'footer.html' %}  
    4 </body>  

    当”include”的模板文件不存在时,程序会抛出异常。你可以加上”ignore missing”关键字,这样如果模板不存在,就会忽略这段”{% include %}”语句。

    1 {% include 'footer.html' ignore missing %}  

    “{% include %}”语句还可以跟一个模板列表:

    1 {% include ['footer.html','bottom.html','end.html'] ignore missing %}  

    上例中,程序会按顺序寻找模板文件,第一个被找到的模板即被加载,而其后的模板都会被忽略。如果都没找到,那整个语句都会被忽略。

  • 相关阅读:
    轻重搭配
    EF的优缺点
    使用bootstrap-select有时显示“Nothing selected”
    IIS发布 HTTP 错误 500.21
    js添加的元素无法触发click事件
    sql server查看表是否死锁
    sql server把一个库表的某个字段更新到另一张表的相同字段
    SQLSERVER排查CPU占用高的情况
    SQL server中如何按照某一字段中的分割符将记录拆成多条
    LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.
  • 原文地址:https://www.cnblogs.com/guolei2570/p/8723192.html
Copyright © 2011-2022 走看看