首页 > 编程语言 >python flask 表单处理Flask-WTF

python flask 表单处理Flask-WTF

时间:2023-06-11 17:32:37浏览次数:41  
标签:name form Flask submit 表单 python flask POST

        涉及到的插件和包有Flask-WTF,WTForms。内容有表单的创建使用流程,一些最佳实践,还有在页面显示提示消息的简单方式,配合Flask内置的 flash()。


Flask的requset对象包含了client端发送过来的所有请求,在request.form中就有POST方法提交过来的表单数据。直接使用这些数据可以搞定表单的操作,不过不方便,于是有了Flask-WTF这个插件,它将WTForms这个包嵌入Flask里,简化Flask下的使用。pip安装会把插件的以来也安装进来:



pip install flask - wtf


WTForms应该也同时被安装了。


跨站请求伪造(Cross-Site Request Forgery,CSRF) 保护

CSRF的原理不具体讲了,很简单,感兴趣直接网上搜即可。


Flask-WTF默认提供对CSRF的保护。应用里需要设置一个加密用的key,Flask-WTF利用这个key生成一个加密的记号来验证request带过来的表单数据。看看实例:



app = Flask ( __name__ )
app . config [ 'SECRET_KEY' ] = 'www.ttlsa.com'


app.config 是应用保存配置的一个字典。可以直接在字典里增加配置。SECRET_KEY这个配置变量被Flask和一些第三方插件使用,对不同的应用配置不同的值增加点可靠性。


另外,这个值最好放到环境变量里,直接写到代码里不太好。


表单类

使用Flask-WTF的时候,每一个表单都是类的形式,这个类需要继承自Form。这个类里定义一些代表表单各类域的对象,每个对象可以有多个验证器(validators)。验证器可以确保用户的输入是有效的。


原例子:



from flask . ext . wtf import Form
from wtforms import StringField , SubmitField
from wtforms . validators import Required
 
class NameForm ( Form ) :
     name = StringField ( 'What is your name?' , validators = [ Required ( ) ] )
     submit = SubmitField ( 'Submit' )

表单中的域在类中都定义成类变量。上例中,NameForm类里有文本域name和提交按钮submit两个。StringField代表有type="text"属性的<input>元素。SubmitField代表有type="submit"属性的<input>元素。构造器的第一个参数是后续渲染表单时候用到的标签(label)。


下例是一个带有文本域和提交按钮的表单例子:



from flask_wtf import Form
from wtforms import StringField , BooleanField , PasswordField , SubmitField
from wtforms . validators import DataRequired
 
class LoginForm ( Form ) :
     openid = StringField ( 'openid' , validators = [ DataRequired ( ) ] )
     remember_me = BooleanField ( 'remember_me' , default = False )
     password = PasswordField ( 'password' , validators = [ DataRequired ( ) ] )
     submit = SubmitField ( 'submit' )


表单中的域在类中都定义成类变量。上例中,LoginForm类里有字符串域openid,复选框remember_me, 密码域password,提交按钮submit。分别代表小面信息:



<input id = "openid" name = "openid" type = "text" value = "" >
<input id = "remember_me" name = "remember_me" type = "checkbox" value = "y" >
<input id = "password" name = "password" type = "password" value = "" >
<input id = "submit" name = "submit" type = "submit" value = "submit" >

构造器的第一个参数是后续渲染表单时候用到的标签(label)。


在StringField里的validators参数定义了一些验证器,这些验证器会在用户提交数据前检查数据是否有效。Required验证器确保提交的内容不能为空。


WTForms提供的各种HTML域:


域类型                   含义
StringField                  文本
TextAreaField                多行文本
PasswordField                密码类文本
HiddenField                  隐藏文本
DateField                    接收给定格式的 datetime . datevalue的文本
DateTimeField                接收给定格式的 datetime . datetimevalue的文本 T
IntegerField                 接收整数的文本
DecimalField                 接收 decimal . Decimal类型值的文本
FloatField                   接收浮点类型值的文本
BooleanField                 选是否的复选框
RadioField                   包含多个互斥选项的复选框
SelectField                  下拉菜单
SelectMultipleField          可多选的下拉菜单
FileField                    文件上传
SubmitField                  提交
FormField                    讲一个表单作为域放入另一个表单里
FieldList                    一组给定类型的域


WTForms提供的各种验证器:


Validator                   Description
Email                        邮箱格式
EqualTo                      比较两个域的值,例如在要求输入两次密码的时候
IPAddress                   IPv4地址
Length                       按字符串的长度验证
NumberRange                  输入数字需在某范围内
Optional                     允许不填,不填的时候就忽略其他验证器
Required                     必填
Regexp                       通过一个正则表达式验证
URL                         URL格式
AnyOf                        属于一组可能值中的一个
NoneOf                       不属于一组可能值中的任何一个


渲染表单

表单的各类域在模板中渲染时表现为可调用的对象。假设将一个NameForm的实例name作为参数传入模板。



< form method = "POST" >
     { { form . name . label } } { { form . name ( ) } }
     { { form . submit ( ) } }
< / form >

这样渲染出来的页面不美观,可以尝试改进下,在调用里传入一些参数,这些参数都会被转化为这个域的属性。然后你可以用CSS自己搞定美化问题:



< form method = "POST" >
     { { form . name . label } } { { form . name ( id = 'my-text-field' ) } }
     { { form . submit ( ) } }
< / form >

上述方式显然很累,之前加入了Bootstrap的支持,Flask-Bootstrap插件其实也对Flask-WTF创建的表单有高层接口的支持,可以用Bootstrap来修饰一下。然后表单的模板就可以简单写成:


{ % import "bootstrap/wtf.html" as wtf % }
{ { wtf . quick_form ( form ) } }


从其他模板import个函数进来之前提到过,wtf.quick_form函数接受一个Flask-WTF的表单,然后用Bootstrap默认的样式渲染。


现在,首页index.html已经改为:



{ % extends "base.html" % }
{ % import "bootstrap/wtf.html" as wtf % }
{ % block title % } Flasky { % endblock % }
{ % block page_content % }
< div class = "page-header" >
     < h1 > Hello , { % if name % } { { name } } { % else % } Stranger { % endif % } ! < / h1 >
< / div >
{ { wtf . quick_form ( form ) } }
{ % endblock % }


这里还用了一个if else结构,如果传入了name,就显示传入的值,否则就显示Stranger。


表单的各类域在模板中渲染时表现为可调用的对象。假设将一个LoginForm的实例openid作为参数传入模板。


< form action = "" method = "post" name = "login" >
     { { form . hidden_tag ( ) } }
         { { form . openid . label } }
         { { form . openid ( size = 80 ) } }
         { % for error in form . openid . errors % }
             < span style = "color: red;" > { { error } } < / span >
         { % endfor % } < br >
 
        密码 :
         { { form . password } }
         { % for error in form . password . errors % }
             < span style = "color: red;" > { { error } } < / span >
         { % endfor % }
         { { form . remember_me } } Remeber Me < / p >
        提交 :
         { { form . submit ( value = '登录' ) } }
< / form >


视图函数中的表单处理

修改hello.py,在index()里处理表单数据。



@ app . route ( '/' , methods = [ 'GET' , 'POST' ] )
def index ( ) :
     name = None
     form = NameForm ( )
     if form . validate_on_submit ( ) :
         name = form . name . data
         form . name . data = ''
     return render_template ( 'index.html' , form = form , name = name )


可以注意到,在app.route装饰器增加了methods参数,这里是把index()注册为GET和POST请求的处理者。如果不提供methods这个参数,试图函数默认只处理GET请求。


这里对index()增加视图函数对POST请求的支持是必须的,因为用户的提交操作使用POST请求更方便处理。使用GET请求来提交表单也可以,但是GET请求的数据都是附加在URL后面作为请求字符串,在浏览器的地址栏可以看到。由此,以及一些其他原因,表单的提交通常都是用POST请求完成的。


继续看改动后的代码,form.validate_on_submit()这个方法,只在用户提交了数据并且数据通过验证器的检查之后,才返回True,其他时候都返回False。用这个方法判断是否对模板进行处理。


看下一般处理流程。用户第一次访问这个应用,使用的是GET请求,不带数据,form.validate_on_submit()这个方法返回False,return就返回一个空白的表单,name值是None。


用户提交了表单后,sercer收到携带数据的POST请求,form.validate_on_submit()这个方法会启动之前设置的Required()验证器,这里name不为空就通过验证,form.validate_on_submit()返回True。然后提取出表单数据保存下来,把表单数据清空。再把name和表单传入render_template(),重新渲染的模板就有了变化。



@ app . route ( '/login' , methods = [ 'GET' , 'POST' ] )
def login ( ) :
     form = LoginForm ( )
     print form . openid
     print form . remember_me
     print form . password
     print form . submit
 
     if form . validate_on_submit ( ) :
         flash ( 'Login requested for OpenID="' + form . openid . data + '", remember_me=' + str ( form . remember_me . data ) + ' password: '
)
         return redirect ( '/index' )
    return render_template ( 'login.html' , title = 'Sign In' , form = form )


标签:name,form,Flask,submit,表单,python,flask,POST
From: https://blog.51cto.com/u_6186189/6458378

相关文章

  • python调用浏览器,实现刷网页小程序
       python打开浏览器,可以做简单的刷网页的小程序and其他有想象力的程序。不过仅供学习,勿用非法用途。python的webbrowser模块支持对浏览器进行一些操作主要有以下三个方法:webbrowser.open(url,new=0,autoraise=True)webbrowser.open_new(url)webbrowser.open_n......
  • python中文乱码问题大总结
        在运行这样类似的代码:#!/usr/bin/envpythons="中文"prints最近经常遇到这样的问题:问题一:SyntaxError:Non-ASCIIcharacter'\xe4'infileE:\coding\python\Untitled6.pyonline3,butnoencodingdeclared;seehttp://www.python.org/peps/pep-0263.......
  • Python中http请求方法库汇总
    最近在使用python做接口测试,发现python中http请求方法有许多种,今天抽点时间把相关内容整理,分享给大家,具体内容如下所示:一、python自带库----urllib2python自带库urllib2使用的比较多,简单使用如下:importurllib2response=urllib2.urlopen('http://localhost:8080/jenkins/api/jso......
  • Python爬虫
    目录PythonSpider第一章爬虫入门1.1爬虫概述1.1.1爬虫原理1.1.2爬虫分类1.1.3爬虫应用1.2爬虫流程1.2.1爬取网页1.2.2解析网页1.2.3存储数据1.3爬虫协议1.3.1Robots协议1.3.2robots.txt文件简介1.3.3robots.txt文件详解1.3.4爬虫准则1.4爬虫环境1.4.1原生Python+......
  • 实验6 turtle绘图与python库应用编程体验
    task1_1代码:fromturtleimport*defmove(x,y):'''画笔移动到坐标(x,y)处'''penup()goto(x,y)pendown()defdraw(n,size=100):'''绘制边长为size的正n变形'''foriinrange(n):......
  • Python中的logging模块
    官方文档基本用法下面的代码展示了logging最基本的用法。#-*-coding:utf-8-*-importloggingimportsys#获取logger实例,如果参数为空则返回rootloggerlogger=logging.getLogger("AppName")#指定logger输出格式formatter=logging.Formatter('%(ascti......
  • Centos 7.4+ 通过anaconda 安装Python3.10
    做记录,在centos里安装3.10版本时,老是报错ssl。或者一些其他问题,做个记录吧。大概用了2天才弄好,主业不是运维所以不太了解在https://www.anaconda.com/官网下载安装,此处自己根据系统、根据版本,自己安装下载地址:https://www.anaconda.com/download#downloads安装好后condai......
  • 实验6 turtle绘图与python库应用编程体验
    实验任务1task1_1.py程序源码:1fromturtleimport*23defmove(x,y):#画笔移动到坐标(x,y)处4penup()5goto(x,y)6pendown()78defdraw(n,size=100):#绘制边长为size的正n变形9foriinrange(n):10forward(size)11......
  • python: Decorators
      #装饰器defprintpy(func):definner_func():func()print("hellopython!GeovinDu")returninner_func#@装饰器@printpydefprinthello():print("helloworld!")#调用printhello()'''De......
  • Python modbus_tk 库源码分析
    modbus_tk源代码分析前言modbus_tcp协议是工业项目中常见的一种基于TCP/IP协议的设备数据交互协议。作为TCP/IP协议的上层协议,modbus_tcp协议涉及到两个概念:client和server。但更标准的叫法应该是master和slave。Slave:TCP/IP协议中的server方Master:TCP/IP协......