flask模板语言

由于Django的模板引擎和Flask中的Jinja2模板引擎有很多一样的地方,所以我将一样的地方总结到了独立的文章中

https://www.cnblogs.com/kuxingseng95/articles/9091027.html

变量

构造上下文

构造上下文前

 return render_template('test01_template.html', my_list=my_list, my_int=my_int, my_dict=my_dict)

构造上下文后

return render_template('test01_template.html', context=context) 
return render_template('test01_template.html', **context) 

比如:

from flask import Flask, render_template

app = Flask(__name__)


@app.route("/index")
def index():
    # 处理业务逻辑
    data = {
        "name": "python",
        "age": 18,
        "my_li": [1, 2, 3, 4, 5, 6, 7],
        "my_int": 0,
        "my_dict": {
            "city": "bj"
        }
    }
    return render_template("code_18_templates.html", **data)


if __name__ == '__main__':
    app.run(debug=True)
View Code

和Django不同,在Flask的Jinja2模板引擎中,{{变量}}中是支持计算的

过滤器

jinja2中过滤器可以传入多个参数。

{{参数1 | 过滤器器(*args) }} 
{{ my_list2 | sum(‘age’) }}

而且支持链式调用

 {{ 'hello world' | reverse | upper }}

自定义过滤器

使用装饰器

from flask import Flask, render_template

app = Flask(__name__)


@app.route("/")
def index():
    return render_template("code_19_filter.html")

# 自定义过滤器
#  定义一个切片函数
@app.template_filter("li2")         # 里面的参数表示过滤器的名字
def li_setup2(li):
    # 每隔一个值获取一下
    step = li[::2]
    return step


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

直接添加到模板过滤器中

from flask import Flask, render_template

app = Flask(__name__)


@app.route("/")
def index():
    return render_template("code_19_filter.html")


#  定义一个切片函数
def li_setup2(li):
    # 每隔一个值获取一下
    return li[::2]


# 自定义过滤器
# 第一个参数:表示自定义的函数名字,
# 第二个参数表示过滤器的名字
app.add_template_filter(li_setup2, "li2")

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

控制语句

与Django模板不同点

for循环后面可以拼接if语句

比较平时使用时我们需要这样:

{% for index in my_list %}   
    {% if index > 5 %}       
        {{ index }}    
    {% endif %} 
{% endfor %}     
View Code

而Flask中可以这样:

{% for index in my_list if index > 5 %}
    {{index}}
{% endfor %}
View Code

比如在判断列表为空的时候

Django和jinja2也不一样

jinja2中

{% for index in my_list %}
    {{index}}
{% else %}
    没有值了
{% endfor %}
View Code

django中

{% for index in my_list %}
    {{index}}
{% empty %}
    没有值了
{% endfor %}
View Code

可以将它看成时Jinja2中的一个函数,它会返回一个模板或者HTML字符串

可以将相同的重复编写的模板代码封装到宏中

使用

标签

{% macro func() %}    
{% endmacro %}

准备宏

{% macro input(label='', type='text', name='', value='') %}    
<label>{{ label }}</label><input type="{{ type }}" name="{{ name }}" value="{{ value }}"><br> 
{% endmacro %}

使用宏

<form action="">
    {{ input(label='⽤用户名:', name='user_name') }}    
    {{ input(label='邮箱:', name='email') }}    
    {{ input(label='密码:', type='password', name='password') }}    
    {{ input(label='确认密码:', type='password', name='password2') }}    
    {{ input(type='submit', value='提交') }} 
</form>

封装宏

为了达到宏的复用,我们可以将宏单独的抽取到指定的html文件中

使用封装的宏

{% import 'macro.html' as func %} 
<form action="">    
    {{ func.input(label='⽤用户名:', name='user_name') }}    
    {{ func.input(label='邮箱:', name='email') }}   
    {{ func.input(label='密码:', type='password', name='password') }}  
    {{ func.input(label='确认密码:', type='password', name='password2') }}   
    {{ func.input(type='submit', value='提交') }} 
</form>

Flask中特有的模板变量和方法

特有变量

比如:

特有变量:

request:获取请求的数据

session:获取session数据

config:获取配置参数

g:获取视图中g变量存储的值

特有方法

url_for()

@app.route("/order/<order_id>")
def order(order_id):    
    return 'order %s' % order_id 

 

超链接中的反向解析,和重定向中的反向解析用法一致

比如在视图函数中定义了

@app.route('/order') 
def order():
    return "order"

然后再模板中

<a href="{{ url_for('order') }}">进⼊入order</a>

 

可以进行反向的解析

反向的解析传参

@app.route("/order/<order_id>")
def order(order_id):
    return "order %s" % order_id

 

<a href="{{ url_for('order', order_id=123) }}">进⼊入order</a>

 

 

get_flashed_messages()

 搭配flask中国的flash()方法使用

flash()用于将视图中准备的提示信息添加到消息队列中

然后模板中使用get_flashed_messages()提取和展示视图中准备的提示信息

使用

{% for message in get_flashed_messages() %}    
    {{message}} 
{% endfor %}

 Flask-WTF表单

首先需要安装 Flask-WTF == 0.14.2

常用模块

表单类

from flask_wtf import FlaskForm 

字段

from wtforms import StringField, PasswordField, SubmitField 

验证器

from wtforms.validators import DataRequired, InputRequired, EqualTo

 例子:

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

<form method="post">

    {{ form.csrf_token }}

    {{ form.user_name.label }}
    <p>{{ form.user_name }}</p>
    {% for msg in form.user_name.errors %}
    <p>{{ msg }}</p>
    {% endfor %}



    {{ form.password.label }}
    <p>{{ form.password }}</p>
    {% for msg in form.password.errors %}
    <p>{{ msg }}</p>
    {% endfor %}



    {{ form.password2.label }}
    <p>{{ form.password2 }}</p>
    {% for msg in form.password2.errors %}
    <p>{{ msg }}</p>
    {% endfor %}





    {{ form.submit }}

</form>


</body>
</html>
前台代码
from flask import Flask, render_template
from flask import request
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, EqualTo

app = Flask(__name__)


class Config(object):
    SECRET_KEY = "fadafsfafsafa"


app.config.from_object(Config)


# FlaskForm:继承flask的表单
class RegisterForm(FlaskForm):
    # StringField :文本输入框
    # validators :用来验证当前的文本输入框
    # DataRequired:必须输入
    user_name = StringField(label="用户名", validators=[DataRequired("必须填写用户名")])
    password = PasswordField(label="密码", validators=[DataRequired("必须填写密码")])
    # EqualTo : 判断两次密码是否相等
    # password :  表示跟上面的密码进行判断,判断两次是否一致
    password2 = PasswordField(label="确认密码", validators=[DataRequired("必须填写密码"), EqualTo("password", "两次密码必须一致")])
    submit = SubmitField(label="提交")


@app.route("/register", methods=["GET", "POST"])
def register():
    if request.method == "GET":
        form = RegisterForm()
        return render_template("code_22_wtf.html", form=form)
    else:
        form = RegisterForm()

        if form.validate_on_submit():

            name = form.user_name.data
            pwd = form.password.data
            pwd2 = form.password2.data
            print(name, pwd)
            return "注册成功"
        else:
            return render_template("code_22_wtf.html", form=form)


if __name__ == '__main__':
    app.run(debug=True)
后台代码

关于csrf

关于csrf的简单介绍:https://www.cnblogs.com/kuxingseng95/articles/9092333.html

防护措施

方案一:在FlaskForm中实现校验

在Flask-WTF扩展中,有一套完整的csrf防护体系

<form method="post">    
    {{ form.csrf_token() }}   
    {{ form.username.label }} {{ form.username }}<br/>    
    {{ form.password.label }} {{ form.password }}<br/>   
    {{ form.password2.label }} {{ form.password2 }}<br/>    
    {{ form.submit }} 
</form>
View Code

方案二:单独使用

from flask.ext.wtf import CSRFPRrotect

CSRFProtect(app)

使用WTF拓展

同方案一

不使用WTF拓展

自己实现校验的所有逻辑

<form method="post" action="/">   
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" /> 
</form>

 

posted @ 2018-05-26 11:26  苦行僧95  阅读(255)  评论(0)    收藏  举报