WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证。
安装:
pip install wtforms
提供多种注册表单方式
from wtforms.fields import simple from wtforms.fields import core from wtforms.fields import html5 from wtforms import validators # 校验规则 from wtforms import widgets # 输入框类别:下拉框、输入框、长文本等等
使用:
简单的注册
from wtforms import Form from wtforms.fields import simple from wtforms import validators class RegFrom(Form): name = simple.StringField(label="用户名", validators=[validators.DataRequired(message="用户名不能为空"), validators.Length(min=2, max=8, message="用户名最小两位,最大8位")]) pwd = simple.PasswordField(label="密码", validators=[validators.DataRequired(message="密码不能为空"), validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}", message=‘密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符‘)]) # pwd = simple.PasswordField(label="密码", validators=[validators.DataRequired(message="密码不能为空"), ]) rep_pwd = simple.PasswordField(label="再次输入密码", validators=[validators.DataRequired(message="重复密码不能为空"), validators.EqualTo("pwd", message="两次密码不一致")])
from flask import Flask, render_template, current_app from flask import Blueprint from flask import request from flask import session from flask_wtforms.forms import register_froms reg = Blueprint(‘reg‘, __name__) @reg.route("/register", methods=["GET", "POST"]) def register(): if request.method == "GET": forms = register_froms.RegFrom() # 注册form表单 return render_template("register.html", forms=forms) forms = register_froms.RegFrom(formdata=request.form) # 将post数据传入 if forms.validate(): # 校验post请求数据 return "ok" return render_template("register.html", forms=forms)
<!DOCTYPE html> <html lang="zn-CH"> <head> <meta charset="UTF-8"> <title>注册</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div> <form action="" method="post" novalidate> <div> {% for from in forms %} <p>{{ from.label }}: {{ from }} {{ from.errors[0] }}</p> {% endfor %} <input type="submit"> </div> </form> </div> </body> </html>
复杂的注册:
from wtforms import Form from wtforms.fields import simple from wtforms.fields import core from wtforms.fields import html5 from wtforms import validators from wtforms import widgets class RegFrom(Form): # name = simple.StringField(label="用户名", # validators=[validators.DataRequired(message="用户名不能为空"), # validators.Length(min=2, max=8, message="用户名最小两位,最大8位")]) # pwd = simple.PasswordField(label="密码", # validators=[validators.DataRequired(message="密码不能为空"), # validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}", # message=‘密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符‘)]) # # pwd = simple.PasswordField(label="密码", validators=[validators.DataRequired(message="密码不能为空"), ]) # rep_pwd = simple.PasswordField(label="再次输入密码", # validators=[validators.DataRequired(message="重复密码不能为空"), # validators.EqualTo("pwd", message="两次密码不一致")]) name = simple.StringField( label=‘用户名‘, validators=[ validators.DataRequired() ], widget=widgets.TextInput(), # 输入框type render_kw={‘class‘: ‘form-control‘}, # 为标签添加类或者属性 default=‘alex‘ # 输入框默认值 ) pwd = simple.PasswordField( label=‘密码‘, validators=[ validators.DataRequired(message=‘密码不能为空.‘) ], widget=widgets.PasswordInput(), render_kw={‘class‘: ‘form-control‘} ) pwd_confirm = simple.PasswordField( label=‘重复密码‘, validators=[ validators.DataRequired(message=‘重复密码不能为空.‘), validators.EqualTo(‘pwd‘, message="两次密码输入不一致") ], widget=widgets.PasswordInput(), render_kw={‘class‘: ‘form-control‘} ) email = html5.EmailField( label=‘邮箱‘, validators=[ validators.DataRequired(message=‘邮箱不能为空.‘), # validators.Email(message=‘邮箱格式错误‘) ], widget=widgets.TextInput(input_type=‘email‘), render_kw={‘class‘: ‘form-control‘} ) gender = core.RadioField( label=‘性别‘, choices=( (1, ‘男‘), (2, ‘女‘), ), coerce=int, # 页面传过来的时候是字符串格式,转成int类型 default=1 ) city = core.SelectField( label=‘城市‘, choices=( (‘bj‘, ‘北京‘), (‘sh‘, ‘上海‘), ) ) hobby = core.SelectMultipleField( label=‘爱好‘, choices=( (1, ‘篮球‘), (2, ‘足球‘), ), coerce=int ) favor = core.SelectMultipleField( label=‘喜好‘, choices=( (1, ‘篮球‘), (2, ‘足球‘), ), widget=widgets.ListWidget(prefix_label=False), option_widget=widgets.CheckboxInput(), coerce=int, default=[1, 2] # 多选框可以为多个默认值 ) def __init__(self, *args, **kwargs): super(RegFrom, self).__init__(*args, **kwargs) self.favor.choices = ((1, ‘篮球‘), (2, ‘足球‘), (3, ‘羽毛球‘)) def validate_pwd_confirm(self, field): """ 自定义pwd_confirm字段规则,例:与pwd字段是否一致 :param field: :return: """ # 最开始初始化时,self.data中已经有所有的值 if field.data != self.data[‘pwd‘]: # raise validators.ValidationError("密码不一致") # 继续后续验证 raise validators.StopValidation("密码不一致") # 不再继续后续验证
在复杂注册的时候,单选或者多选框的值可能是从数据库中取到的,但是在数据库中添加一个选项时,页面并不会跟随更新,只有重启服务才会显示。
解决办法:请求过来执行视图,视图中实例forms表单类对象,在forms表单类中重写__init__方法,实现每次请求都重新去数据库中取值,但是别忘了设置pymysql返回元祖类型的数据
from wtforms import Form from wtforms.fields import simple from wtforms.fields import core from wtforms.fields import html5 from wtforms import validators from wtforms import widgets import helper class UserForm(Form): city = core.SelectField( label=‘城市‘, choices=(), # 在__init__中从数据库中获取 coerce=int ) name = simple.StringField(label=‘姓名‘) def __init__(self,*args,**kwargs): super(UserForm,self).__init__(*args,**kwargs) self.city.choices=helper.fetch_all(‘select id,name from tb1‘,[],type=None)
import pymysql from DBUtils.PooledDB import PooledDB, SharedDBConnection import pymysql POOL = PooledDB( creator=pymysql, # 使用链接数据库的模块 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数 mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建 maxcached=5, # 链接池中最多闲置的链接,0和None不限制 maxshared=3, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always host=‘127.0.0.1‘, port=3306, user=‘root‘, password=‘123456‘, database=‘s9day119‘, charset=‘utf8‘ ) def connect(type): conn = POOL.connection() cursor = conn.cursor(cursor=type) return conn,cursor def connect_close(conn,cursor): cursor.close() conn.close() def fetch_all(sql,args,type=pymysql.cursors.DictCursor): # type=pymysql.cursors.DictCursor返回的数据为字典,传入None时,返回元祖 conn,cursor = connect(type) cursor.execute(sql, args) record_list = cursor.fetchall() connect_close(conn,cursor) return record_list def fetch_one(sql, args): conn, cursor = connect() cursor.execute(sql, args) result = cursor.fetchone() connect_close(conn, cursor) return result def insert(sql, args): conn, cursor = connect() row = cursor.execute(sql, args) conn.commit() connect_close(conn, cursor) return row
原文:https://www.cnblogs.com/aizhinong/p/12770655.html