Flask | Jinja2 (二)

控制结构和代码重用

Posted by Haauleon on June 16, 2018

控制结构

   Python 开发前后端不分离 Web 项目的时候,前端通常使用 Jinja2 模板语言。为了改变模板的渲染流程,需要用到 Jinja2 的控制结构。

一、if 条件判断语句

需求:用户从客户端发送请求并传入一串身份证号码,应用程序需要对这串身份证号码进行检验,并返回最终的检验结果。


方式一:在视图函数中进行检验
在 /hello.py 中定义一个视图函数 checkIDCard(strNum) 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from flask import Flask
import time
app = Flask(__name__)

@app.route('/user/check/<strNum>')
def checkIDCard(strNum):
    # 身份证号码长度判断
    if len(strNum) != 15 and len(strNum) != 18:
        return "填写的身份证号码长度不正确,请重新填写!"
    else:    
        if len(strNum) == 18:   
            # 判断身份证号码的日期是否有效
            strDate = strNum[6:14]
            try:
                time.strptime(strDate, "%Y%m%d")
            except ValueError:
                return "身份证号码验证失败,请重新填写!"

            # 排除长度为18的身份证号码的最后一位数字后进行字符串格式判断
            if strNum[:17].isnumeric() == False:
                return "填写的身份证号码格式不正确,请重新填写!"
            else:
                return "身份证号码验证成功!"

实现效果如下:



方式二:在模板中进行检验
在 /hello.py 中定义一个视图函数 checkIDCard(strNum) 。

1
2
3
4
5
6
from flask import Flask, render_template
app = Flask(__name__)

@app.route('/user/check/<strNum>')
def checkIDCard(strNum):
    return render_template('check.html', strNum=strNum)

在 /templates/check.html 中验证用户的身份证号码,相当于前端做判断。

实现效果如下:



二、for 循环语句

在 /hello.py 中定义一个视图函数 forprint() 。

1
2
3
4
5
6
7
from flask import Flask, render_template
app = Flask(__name__)

@app.route('/forprint')
def forprint():
    dataList = ["美丽的", "可爱的", "迷人的", "温柔的", "阳光的", "善良的"]
    return render_template('for.html', dataList=dataList)

在 /templates/for.html 中写一个模板来渲染这组列表的元素。

实现效果如下:



三、重复使用宏

  宏(macro)类似于 Python 代码中的函数,作用是把常用行为作为可重用的函数来取代 手工复制粘贴的重复工作,因此使用宏可以节省大量的代码。

方式一 在当前模板内使用宏
仍然借用 /hello.py 中的视图函数 forprint() 。

1
2
3
4
5
6
7
from flask import Flask, render_template
app = Flask(__name__)

@app.route('/forprint')
def forprint():
    dataList = ["美丽的", "可爱的", "迷人的", "温柔的", "阳光的", "善良的"]
    return render_template('macro.html', dataList=dataList)

在 /templates/macros.html 中定义一个宏来打印传进来的参数。

实现效果如下:


方式二 在其他模板中导入宏
  在真实的开发中,会将一些常用的宏单独放在一个文件中,在需要使用的时候,再从这个文件中进行导入。import 语句的用法跟 python 中的 import 类似,可以直接import...as...,也可以from...import...或者from...import...as...

仍然借用 /hello.py 中的视图函数 forprint() 。

1
2
3
4
5
6
7
from flask import Flask, render_template
app = Flask(__name__)

@app.route('/forprint')
def forprint():
    dataList = ["美丽的", "可爱的", "迷人的", "温柔的", "阳光的", "善良的"]
    return render_template('use_macro.html', dataList=dataList)

在 /templates/use_macro.html 中使用模板 /templates/macros.html 的宏。

实现效果如下:


方式三 在多处地方重复使用宏
  include 标签相当于是直接将指定的模板中的代码复制粘贴到当前位置。

仍然借用 /hello.py 中的视图函数 forprint() 。

1
2
3
4
5
6
from flask import Flask, render_template
app = Flask(__name__)

@app.route('/forprint')
def forprint():
    return render_template('include_macro.html')

先定义一个可重复使用的模板 /templates/sample_macro.html 。

1
<h3>可爱的我要睡了!</h3>

再定义一个模板 /templates/include_macro.html ,在多处地方使用模板 /templates/sample_macro.html 。

实现效果如下:



四、模板继承

  模板继承类似于 Python 代码中的类继承,作用是重复使用代码。Jinja2 使用blockendblock指令在基模板中定义内容区块(比如 head、title、content 和 body 这种常见的区块),使用block 标记区块是为了跟 Jinja2 说明衍生模板可以覆盖基模板中的这些区块/占位符。通俗来说,相当于在基模板中使用block先挖个坑,然后在衍生模板中去填上这些坑。一句讲晒,基模板中定义的区块可以在衍生模板中被覆盖。

先定义一个基模板 /templates/base.html,使用block标记可被衍生模板填充的三个区块(head、title 和 body)。



  extends标签是衍生模板中的第一个标签。它的作用是声明这个模板衍生自哪个基模板,并且在extends指令之后,基模板中使用block标记的区块将重新被定义被覆盖。如果基模板和衍生模板中的同名区块有各自不同的内容,则最终显示的是衍生模板的内容。在衍生模板的区块内可调用super()来引用基模板中同名区块的内容(就是直接复制过来,然后再增加一些新的内容即可)。

再定义一个衍生模板 /templates/heyman.html,衍生自 /templates/base.html。