flask中jinjia2的学习

flask中的jinjia2文章目录


前言

Jinja2:是Python的Web项目中被广泛应用的模板引擎,是由Python实现的模板语言,Jinja2 的作者也是 Flask 的作
者。他的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。
jinja2之所以被广泛使用是因为它具有以下优点:
1、相对于Template,jinja2更加灵活,它提供了控制结构,表达式和继承等。
2、相对于Mako,jinja2仅有控制结构,不允许在模板中编写太多的业务逻辑。
3、相对于Django模板,jinja2性能更好。
4、Jinja2模板的可读性很棒。
要渲染一个模板,通过 render_template 方法即可。


提示:以下是本篇文章正文内容,下面案例可供参考

一、传参

1.传参需要用到的模板是render_template,这个模板可以读取到templates下的html等文件,渲染到客户端界面。
2,渲染的内容可以是单个,也可以是列表,一般如果想将字典打散成
关键字参数可以在参数的前面加 **

from flask import Flask,render_template

app = Flask(__name__)


student={'name':'zhangsan','age':38,'gender':'女'}

student_list=[
    {'name':'zhangsan','age':38,'gender':'女'},
    {'name':'lishi','age':29,'gender':'男'},
    {'name':'wangwu','age':18,'gender':'女'}

]

student_dict={
    'a':{'name':'zhangsan','age':38,'gender':'女'},
    'b':{'name':'lishi','age':29,'gender':'男'},
    'c':{'name':'wangwu','age':18,'gender':'女'}

}
#打散传参 做成关键字
@app.route('/test1')
def test1():  # put application's code here
    return render_template('01.html',**student) #打散

#传多个参数时,可以选择列表的形式
@app.route('/test2')
def test2():
    return render_template('02.html',stu_list=student_list)

#选择字典的形式传参
@app.route('/test3')
def test3():
    return render_template('03.html',stu_dict=student_dict)


if __name__ == '__main__':
    app.run()

对应的template下的HTML文件为

1.HTML
2,这里主要用到 if else判断语句,主要用来判断对应的年龄是否大于18,大于18输出的是“已成年”,否则输出else下的内容 “未成年”。
3,{{ 定义属性名 }} 可以读取出我们在py文件定义的值,例如student={‘name’:‘zhangsan’,‘age’:38,‘gender’:‘女’} 可以以name,age 作为关键字取值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>第一个模板</title>
</head>
<body>
学生姓名:{{ name }},年龄:
{% if age>=18 %}
    已经成年
{% else %}
    未成年
{% endif %}
,性别:{{ gender }}
</body>
</html>

2.HTML

  • 这里因为是以列表的形式传参,含有多个人字典,所以传参时要使用到 stu_list 函数。
  • 在使用前端语法,生成一个表格
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>第二个模板</title>
</head>
<body>

{{ stu_list }}

<table border="1px">
    <tr>
        <td>序号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>性别</td>
    </tr>
    {% for stu in stu_list %}
        <tr>
            <td>{{ loop.index }}</td> <!-- loop.index 显示序号-->
            <td>{{ stu.name }}</td>
            {% if stu.age >=60 %}
                <td>已退休</td>
            {% elif stu.age >=18 and stu.age <60 %}
                <td>成年</td>
            {% else %}
                <td>未成年</td>
            {% endif %}
            <td>{{ stu.gender }}</td>
        </tr>

    {% endfor %}

</table>
</body>
</html>

3.HTML

  • 以字典的形式传参,需要用到 stu_dict 函数
  • student_dict={
    ‘a’:{‘name’:‘zhangsan’,‘age’:38,‘gender’:‘女’},
    ‘b’:{‘name’:‘lishi’,‘age’:29,‘gender’:‘男’},
    ‘c’:{‘name’:‘wangwu’,‘age’:18,‘gender’:‘女’} 这里因为是字典包字典的形式,所以 {% for stu_key,stu in stu_dict.items() %} 遍历时传两个参数,第一个参数stu_key 继承的是 a b c ,第二参数stu 继承的是第二字典里所有的那内容({‘name’:‘zhangsan’,‘age’:38,‘gender’:‘女’}), 使用items() 是把里面的内容全部显示出来
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>第二个模板</title>
</head>
<body>
{{ stu_dict }}

<table border="1px">
    <tr>
        <td>序号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>性别</td>
    </tr>
    {% for stu_key,stu in stu_dict.items() %} <!-- items显示全部-->
        <tr>
            <td>{{ loop.index }},key:{{ stu_key }}</td> <!-- loop.index 显示序号-->
            <td>{{ stu.name }}</td>
            {% if stu.age >=60 %}
                <td>已退休</td>
            {% elif stu.age >=18 and stu.age <60 %}
                <td>成年</td>
            {% else %}
                <td>未成年</td>
            {% endif %}
            <td>{{ stu.gender }}</td>
        </tr>

    {% endfor %}

</table>
</body>
</html>

在jinjia2中有三种语法:

1,控制结构 (逻辑代码){% %}
2,变量取值{{ }}
3,注释{# #}

二、过滤器

  1. 过滤器的原理:过滤器的本质就是函数。有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用 Python 中的某些方法,那么这就用到了过滤器。
  2. 也是通过在py文件调用templates下的文件
  3. 常用的过滤器有:
过滤器名称 说明
safe 渲染时值不转义
capitialize 把值的首字母转换成大写,其他子母转换为小写
lower 把值转换成小写形式
upper 把值转换成大写形式
title 把值中每个单词的首字母都转换成大写
trim 把值的首尾空格去掉
striptags 渲染之前把值中所有的HTML标签都删掉
join 拼接多个值为字符串
replace 替换字符串的值
round 默认对数字进行四舍五入,也可以用参数进行控制
int 把值转换成整型

1,字符串过滤器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>字符串的过滤器</title>
</head>
<body>
{# 当变量数据没有传入,可以给变量设置默认值 #}
<p> {{ name | default('not test') }}</p><br>

{# 字符串的大小写转换 #}
<p> {{ 'XWX' | lower }}</p><br>

{# 字符转换 #}
<p> {{ 'hello ywx' | reverse }}</p><br>

<p> {{ '今天是%d号,天气%s' | format(17,'下雨') }}</p>

{# HTML转义,safe 渲染时值不转义#}
<p> {{ '<em>name</em>' | safe }}</p>
</body>
</html>

2,数字过滤器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数字过滤器</title>
</head>
<body>
{# 四舍五入的转换 #}
<p>{{ 3.1415 | round }}</p><br>
{# 小数点后两位 #}
<p>{{ 3.1415 | round(2) }}</p><br>

{# 取绝对值 #}
<p>{{ -1001 | abs }}</p><br>
</body>
</html>

3,列表过滤器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表过滤器</title>
</head>
<body>
{# 定义了一个numbers的变量 #}
{% set numbers=[3,2,5,6,1,8] %}

{# 取第一个值 #}
<p>{{ numbers | first }}</p><br>

{# 算个数 #}
<p>{{ numbers | length }}</p><br>

{# 求和 #}
<p>{{ numbers | sum }}</p><br>

{# 升序 #}
<p>{{ numbers | sort }}</p><br>

{# 并接#}
<p>{{ numbers | join('-') }}</p><br>
</body>
</html>

4,字典过滤器

主要讲一下分组,用到groupby(‘gender’) 函数,按照gender这个属性值来分组的
group.grouper 按照刚才那个属性值来分组并且生成该组名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>字典过滤器</title>
</head>
<body>
{% set students=[
    {'name':'zs','age':32,'gender':'女'},
    {'name':'ls','age':22,'gender':'男'},
    {'name':'ww','age':24,'gender':'女'},
    
] %}
{# 根据学生的年龄排序 #}
<ul>
    {% for stu in students | sort(attribute='age',reverse=false) %} <!--  reverse=false升序-->
        <li>{{ stu.name }},{{ stu.age }},{{ stu.gender }}</li>
    {% endfor %}
</ul>
{# 上面的数据分组,每组变成一个子列表 #}
<ul>
    {% for group in students |groupby('gender')  %}
        <li>{{ group.grouper}}</li> <!-- 组名-->
        {% for stu in group.list  %}
            <li>{{ stu.name }},{{ stu.gender }}</li>
        {% endfor %}
    {% endfor %}
</ul>

{# 取出字典的某列,组成一个大的列表,然后再把列表变成字符串 #}
<p>{{ students | map(attribute='name') | join('-')}}</p><br>
</body>
</html>

5,自定义过滤器

1,有时候根据自己不同业务需求,则需要定义满足自己业务需求的过滤器
2.这里有两种调用方法:第一种用到jinja_env.filters[ ‘’ ]函数,第二种类似装饰器@app.template_filter(’ ') 里面定义的是过滤器的名字
3,不管用到的是那种调用方式,第一种[ ] 和第二种()里的传入的值都要以HTML里定义的一致

from flask import Flask,render_template

app = Flask(__name__)

#自定义过滤器
def get_top_3(lit): #取列表的前三个
    return lit[:3]

#第一种调用方式方式
app.jinja_env.filters['get_top']=get_top_3

#第二种添加装饰器调用
@app.template_filter('get_qu')
def get_qu(lit): #计算列表中每个元素的平方
    return list(map(lambda x:x*x,lit))

@app.route('/test5')
def test5():
    return render_template('自定义的过滤器.html')
if __name__ == '__main__':
    app.run()

调用的HTML文件
这里的 get_top , get_qu 要和要和在py文件的过滤器名字一致

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义的过滤器</title>
</head>
<body>
<p>{{ [1,2,3,4,5,6,7] | get_top }}</p><br>
<p>{{ [1,2,3,4,5,6,7] | get_qu }}</p><br>
</body>
</html>

三、测试器

测试器本质上也是一个函数,它的第一个参数就是待测试的变量,在模板中使用时可以省略去。如果它有第二个参
数,模板中就必须传进去。测试器函数返回的必须是一个布尔值,这样才可以用来给if语句作判断。

1. 常用测试器

{# 检查变量是否被定义,也可以用undefined检查是否未被定义 #}
{% if name is defined %}
<p>Name is: {{ name }}</p>
{% endif %}
{# 检查是否所有字符都是大写 #}
{% if name is upper %}
<h2>"{{ name }}" are all upper case.</h2>
{% endif %}
{# 检查变量是否为空 #}
{% if name is none %}
<h2>Variable is none.</h2>
{% endif %}
{# 检查变量是否为字符串,也可以用number检查是否为数值 #}
{% if name is string %}
<h2>{{ name }} is a string.</h2>
{% endif %}
{# 检查数值是否是偶数,也可以用odd检查是否为奇数 #}
{% if 2 is even %}
<h2>Variable is an even number.</h2>
{% endif %}
{# 检查变量是否可被迭代循环,也可以用sequence检查是否是序列 #}
{% if [1,2,3] is iterable %}
<h2>Variable is iterable.</h2>
{% endif %}
{# 检查变量是否是字典 #}
{% if {'name':'test'} is mapping %}
<h2>Variable is dict.</h2>


# 四、模板的继承
# 五、url_for函数
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

# 二、使用步骤
## 1.引入库
>代码如下(示例):

```c
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

2,自定义测试器

  • 自定义测试器用来满足自己的的测试需求
  • 这里测试器也有两种调用方法: 第一种通过调用类似装饰器@app.template_test(‘测试器名字’ ) ,第二种#app.jinja_env.tests[‘测试器名字’] = 视图函数
  • 在html文件也是一样的 测试器的名字要保持一致
from flask import Flask,render_template
import re
app = Flask(__name__)

@app.route('/test1')
def test1():
    return render_template('自定义测试器.html',name='YWX')

@app.template_test('test2')
def test2(phone): #测试手机号是否合法
    phone_re=r'1[3-9]\d{9}'
    return re.match(phone_re,phone)

@app.template_test('test3') #是不是以什么开头
def test3(my_str,suffix):
    return my_str.lower().startswith(suffix.lower())

#app.jinja_env.tests['is_phone'] = test3
if __name__ == '__main__':
    app.run(host='0.0.0.0',port=8080,debug=True)

html代码示例
这里 is 后面接的是在py文件定义测试器名字

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义测试器</title>
</head>
<body>

{% if '10020420' is test2 %}
    <p>是手机号</p>
{% else %}
    <p>不是手机号</p>
{% endif %}

{% if 'hello' is test3('he') %}
    <p>是以he开头</p>
{% else %}
    <p>不是</p>
{% endif %}
</body>
</html>

四,模板的继承

一般我们的网站虽然页面多,但是很多部分是重用的,比如页首,页脚,导航栏之类的。对于每个页面,都要写这
些代码,很麻烦。
Flask的Jinja2模板支持模板继承功能,省去了这些重复代码。
所以那些重用的代码,我们可以写在一个html文件,到时候来调用就可以了。

重用的这些代码文件,我们给它取名字称父模板,当然也可以自己命名。
用到block 这个函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父模板</title>
</head>
<body>
{% block temp1 %}
    页面的头部<br>
    <hr>
{% endblock %}

<p>父模板的中间内容</p>

{% block temp2 %}
    <hr>
    <p>页面的尾部</p><br>
{% endblock %}

</body>
</html>

子模版,在这个模板的要继承父模板里的内容
用到{% extends “自己定义的父模板名字.html” %} 来继承父模板的内容
注意: {{ super() }} 就表示了通用模板里的内容 在一个项目HTML中,块被定义多次,是会被覆盖的。有时候,我们想引用块的内容,又不想写一串很长的块内容,这时候可以用下面的语法,不管在哪个html文件里定义的都可以,只要有继承关系

{% extends "自己定义的父模板名字.html" %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>子模板</title>
</head>
<body>
{% block temp2 %}
    {{ super() }}
    <p>子模板的内容</p>
{% endblock %}
</body>
</html>

include标签

  • 这个标签相当于是直接将指定的模版中的代码复制粘贴到当前位置。 include 标签,如果想要使用父模版中的变
    量,直接用就可以了。 include 的路径,也是跟 import 一样,直接从 templates 根目录下去找,不要以相对路
    径去找。

  • 做项目时代码量太大,全部在一个文件可能会让我们感到混乱,所以用到include标签可以灵活的让我们调用

  • 这里通过{% include ‘header.html’ %}
    {% include ‘foor.html’ %} 就可以调用header.html ,foor.html两个文件的代码到当前文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>include标签</title>
</head>
<body>

{% include 'header.html' %}

页面中间的内容

{% include 'foor.html' %}
</body>
</html>
  • header.html
<P>页面头部</P>
    <hr>
  • foor.html
<hr>
    <p>页面尾部</p>

五, url_for函数

模版中的 url_for 跟我们后台视图函数中的 url_for 使用起来基本是一模一样的。也是传递视图函数的名字,也
可以传递参数。使用的时候,需要在 url_for 左右两边加上一个 {{ url_for(‘func’) }}

  • 这里一个url_for的作用是调用user_login视图函数,并且生成动态路由,当点击登录时实现登录功能
  • 第二个 url-for 是一个超链接,把static目录的OIP-C.jpg 的图片展现到客户端(浏览器)界面。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>URL_FRO</title>
</head>
<body>
<a href="{{ url_for('user_login',un='zs',id=2) }}">登录</a>

<img src="{{ url_for('static',filename='OIP-C.jpg') }}">
</body>
</html>

总结

  • 小白对jinjia2的总结,有不对或不足的地方还望大佬指证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值