wtf 表单

首先说明wtf不同于flask-wtf,前者时后者的加强版

下面说明常用字段,钩子函数,重写__init__方法

from flask import Flask, render_template, request
from wtforms import Form
from wtforms import validators            
from wtforms import widgets
from wtforms.fields import simple
from wtforms.fields import core
from wtforms.fields import html5


app = Flask(__name__)


class LoginForm(Form):
    name = simple.StringField(
        label='用户名:',                                               # input标签,前端 .字段.label
        validators=[
            validators.DataRequired(message='用户名不能为空'),          # 为空错误信心
            validators.Length(min=2, max=6, message='用户名长度必须大于%(min)d且小于%(max)d'),  # 长度错误信息
        ],
        widget=widgets.TextInput(),                                   # 插件
        render_kw={'class': 'form-control'},                          # 自定义属性
        default='aki'                                                 # 默认值
    )
    pwd = simple.PasswordField(
        label='密码:',
        validators=[
            validators.DataRequired(message='密码不为空'),
            validators.Length(min=8, message='密码不少于八位'),
            # validators.Regexp(regex="正则匹配")
        ],
        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
    )
    # 下拉框
    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]
    )
    # 重写__init__方法,解决更新数据库,前端拿到数据无法刷新的问题,静态字段问题,本身不会影响表单
    # def __init__(self, *args, **kwargs):
    #     super(LoginForm, self).__init__(*args, **kwargs)
    #     self.city.choices = '数据库查询的方法'

    # 自定义构造函数 必须按 validate_字段名 格式
    def validate_name(self, field):
        print("aa", field.data)       # 字段内容
        if not field.data.startswith('x'):
            raise validators.ValidationError('必须以x开头')
            # 对同一个字段继续后续验证
            # raise validators.StopValidation('xx')
            # 对同一字段不在继续后面的验证


@app.route('/', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        form = LoginForm()
        return render_template('index.html', form=form)
    form = LoginForm(formdata=request.form)
    if form.validate():
        print("验证通过的数据", form.data)
        return "ok"
    else:
        print(form.errors)
        return render_template('index.html', form=form)


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

前端显示

<form method="POST">
   {% for field in form %} 
         {{ field.label }} : {{ field }} 
         {{ field.error[0] }}
   {% endfor %} 

 

字段
StringField文本字段
TextAreaField多行文本字
PasswordField密码文本字
HiddenField隐藏文本字段
的DateField文本字段,值为datetime.date格
DateTimeField字段文本字段,值为datetime.datetime格式
IntegerField文本字段,值为整数
DecimalField文本字段,值为dec​​imal.Decimal
FloatFiel文本字段,值为浮点数
BooleanField复选框,值为真和假
RadioField一组单选框
SelectField下拉列表
SelectMultipleField下拉列表,可选择多个值
的FileField文件上传字段
SubmitField表单提交按钮
FormField把表单作为字段嵌入另一个表单
FieldList中一组指定类型的字段
验证函数,验证。
电子邮件验证电子邮件地址 
等于比较两个字段的值;常用于要求输入两次密码进行确认的情况
IP地址验证IPv4网络地址
长度验证输入字符串的长度
NumberRange验证输入的值在数字范围内
可选的无输入值时跳过其他验证函数
需要确保字段中有数据
正则表达式使用正则表达式验证输入值
网址验证URL
任何确保输入值在可选值列表中
没有确保输入值不在可选值列表中
DataRequired确保转换类型后字段中有数据
InputRequired确保转换类型前字段中有数据
MAC地址验证MAC地址
UUID验证UUID
  

下面是带CSRF的

from flask import Flask, render_template, request, redirect, session
from wtforms import Form
from wtforms.csrf.core import CSRF
from wtforms.fields import core
from wtforms.fields import html5
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets
from hashlib import md5

app = Flask(__name__, template_folder='templates')
app.debug = True


class MyCSRF(CSRF):


    def setup_form(self, form):
        self.csrf_context = form.meta.csrf_context()
        self.csrf_secret = form.meta.csrf_secret
        return super(MyCSRF, self).setup_form(form)

    def generate_csrf_token(self, csrf_token):
        gid = self.csrf_secret + self.csrf_context
        token = md5(gid.encode('utf-8')).hexdigest()
        return token

    def validate_csrf_token(self, form, field):
        print(field.data, field.current_token)
        if field.data != field.current_token:
            raise ValueError('Invalid CSRF')


class TestForm(Form):
    name = html5.EmailField(label='用户名')
    pwd = simple.StringField(label='密码')

    class Meta:
        # -- CSRF
        # 是否自动生成CSRF标签
        csrf = True
        # 生成CSRF标签name
        csrf_field_name = 'csrf_token'

        # 自动生成标签的值,加密用的csrf_secret
        csrf_secret = 'xxxxxx'
        # 自动生成标签的值,加密用的csrf_context
        csrf_context = lambda x: request.url
        # 生成和比较csrf标签
        csrf_class = MyCSRF

        # -- i18n
        # 是否支持本地化
        # locales = False
        locales = ('zh', 'en')
        # 是否对本地化进行缓存
        cache_translations = True
        # 保存本地化缓存信息的字段
        translations_cache = {}


@app.route('/index/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        form = TestForm()
    else:
        form = TestForm(formdata=request.form)
        if form.validate():
            print(form)
    return render_template('index.html', form=form)


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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值