Flask表单

6.4 表单

使用Flask-WTF表单扩展,可以帮助进行CSRF验证,帮助我们快速定义表单模板,而且可以帮助我们在视图中验证表的数据

 

pip install Flask-WTF

6.4.1 不使用Flask-WTF扩展时,表单需要自己处理

 

#模板文件
<form method='post'>
    <input type="text" name="username" placeholder='Username'>
    <input type="password" name="password" placeholder='password'>
    <input type="submit">
</form>

 

from flask import Flask,render_template,request

@app.route('/login',methods=['GET','POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        print username,password
        return “success”
    else:
        return render_template(“login.html”)

6.4.2 使用Flask-WTF扩展

需要设置 SECRET_KEY 的配置参数,前端设置csrf_token

模板页:

 

 

    <form method="post">
     
     # 设置csrd_token {{ 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>

 

视图函数

# coding:utf-8

from flask import Flask, render_template, redirect, url_for, session
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, EqualTo


app = Flask(__name__)

app.config["SECRET_KEY"] = "xhosd6f982yfhowefy29f"


# 定义表单的模型类
class RegisterForm(FlaskForm):
    """自定义的注册表单模型类"""
    #                       名字            验证器/验证器
    # DataRequired 保证数据必须填写,并且不能为空
    user_name = StringField(label=u"用户名", validators=[DataRequired(u"用户名不能为空")])
    password = PasswordField(label=u"密码", validators=[DataRequired(u"密码不能为空")])
    password2 = PasswordField(label=u"确认密码", validators=[DataRequired(u"确认密码不能为空"),
                                                         EqualTo("password", u"两次密码不一致")])
    submit = SubmitField(label=u"提交")
@app.route("/register", methods=["GET", "POST"])
def register():
    # 创建表单对象, 如果是post请求,前端发送了数据,flask会把数据在构造form对象的时候,存放到对象中
    form = RegisterForm()

    # 判断form中的数据是否合理
    # 如果form中的数据完全满足所有的验证器,则返回真,否则返回假
    if form.validate_on_submit():
        # 表示验证合格
        # 提取数据
        uname = form.user_name.data
        pwd = form.password.data
        pwd2 = form.password2.data
        print(uname, pwd, pwd2)
        session["user_name"] = uname
        return redirect(url_for("index"))

    return render_template("register.html", form=form)

 

6.5.1 if语句

{% if %} {% endif %}

6.5.2 for语句

{% for item in samples %} {% endfor %}

 

6.6.1 不带参数宏的定义与使用

定义:

{% macro input() %}

  <input type="text"

         name="username"

         value=""

         size="30"/>

{% endmacro %}

 

使用

{{ input() }}

 

6.6.2 带参数宏的定义与使用

定义

{% macro input(name,value='',type='text',size=20) %}

    <input type="{{ type }}"

           name="{{ name }}"

           value="{{ value }}"

           size="{{ size }}"/>

{% endmacro %}

 

使用

{{ input(value='name',type='password',size=40)}}

 

6.6.3 将宏单独封装在html文件中

 

文件名可以自定义macro.html

 

{% macro input() %}

 

    <input type="text" name="username" placeholde="Username">

    <input type="password" name="password" placeholde="Password">

    <input type="submit">

{% endmacro %}

 

在其它模板文件中先导入,再调用

 

{% import 'macro.html' as func %}

{% func.input() %}

6.4 模板继承

父模板:base.html

  {% block top %}
    顶部菜单
  {% endblock top %}

  {% block content %}
  {% endblock content %}

  {% block bottom %}
    底部
  {% endblock bottom %}

 

子模板:

  {% extends 'base.html' %}
  {% block content %}
   需要填充的内容
  {% endblock content %}

 

模板继承使用时注意点:

  • 不支持多继承。
  • 为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
  • 不能在一个模板文件中定义多个相同名字的block标签。
  • 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。

6.5 模板包含

Jinja2模板中,除了宏和继承,还支持一种代码重用的功能,叫包含(Include)。它的功能是将另一个模板整个加载到当前模板中,并直接渲染。

示例:

include的使用

{\% include 'hello.html' %}

包含在使用时,如果包含的模板文件不存在时,程序会抛出TemplateNotFound异常,可以加上ignore missing关键字。如果包含的模板文件不存在,会忽略这条include语句。

示例:

include的使用加上关键字ignore missing

{\% include 'hello.html' ignore missing %}

  • 宏、继承、包含:
    • 宏(Macro)、继承(Block)、包含(include)均能实现代码的复用。
    • 继承(Block)的本质是代码替换,一般用来实现多个页面中重复不变的区域。
    • 宏(Macro)的功能类似函数,可以传入参数,需要定义、调用。
    • 包含(include)是直接将目标模板文件整个渲染出来。

 

6.6 flask在模板中使用特殊变量和方法

6.6.1 config

config 对象就是Flask的config对象,也就是 app.config 对象。

{{ config.SQLALCHEMY_DATABASE_URI }}

6.6.2 request

 就是 Flask 中表示当前请求的 request 对象,request对象中保存了一次HTTP请求的一切信息。

6.6.3 url_for

 

request常用的属性如下:

属性说明类型
data 记录请求的数据,并转换为字符串 *
form 记录请求中的表单数据 MultiDict
args 记录请求中的查询参数 MultiDict
cookies 记录请求中的cookie信息 Dict
headers 记录请求中的报文头 EnvironHeaders
method 记录请求使用的HTTP方法 GET/POST
url 记录请求的URL地址 string
files 记录请求上传的文件 *

{{ request.url }}

6.6.3 url_for 

url_for() 会返回传入的路由函数对应的URL,所谓路由函数就是被 app.route() 路由装饰器装饰的函数。如果我们定义的路由函数是带有参数的,则可以将这些参数作为命名参数传入。

{{ url_for('index') }}

{{ url_for('post', post_id=1024) }}

6.6.4 get_messages  (闪现)

get_flashed_messages方法:

返回之前在Flask中通过 flash() 传入的信息列表。把字符串对象表示的消息加入到一个消息队列中,然后通过调用 get_flashed_messages() 方法取出。

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

 

from flask import Flask, render_template, flash

app.config["SECRET_KEY"] = "SDHFOSDF"
@app.route("/")
def index():

    if flag:
        # 添加闪现信息
        flash("hello1")
        flash("hello2")
        flash("hello3")
        global flag
        flag = False

    return render_template("index.html")
    <h1>闪现</h1>
    {% for msg in get_flashed_messages() %}
        <p>{{msg}}</p>
    {% endfor %}

 

 

 

 

 


 

posted @ 2018-11-20 13:51  wsg-python  阅读(210)  评论(0)    收藏  举报