表单验证wtform的使用

本文介绍了如何在PythonFlask项目中使用WTForm进行表单验证,包括基本验证规则、安装方法、字段类型(如StringField和PasswordField)、CSRF防护以及自定义验证和验证码生成。
摘要由CSDN通过智能技术生成

对于python的web轻量级框架flask来说,他是没有包含表单验证的,所以当我们处理复杂表单验证的时候会很麻烦,这时候就需要使用flask为我们推荐的第三方轮子wtform

这里有一个flask-wtform就跟flask-bootstrapflask-sqlalchemy一样,将wtform的一些内容更改变得更加适配web框架,减少了一些不必要的功能。

安装

使用pip进行安装wtform

pip3 install flask-wtform

快速开始

你可以定义一个继承FlaskForm的类

class UserForm(FlaskForm):
         name=stringField('name',validators=[])

他还有下图的这些Field。
在这里插入图片描述

上面的stringField其实就是你的表单里的text文本框。参数的那么指的是你的表单text的名字,而validators就是校验链了。我们可以点进wtforms源码看一看。
在这里插入图片描述
这些判断全部可以放在validators.

__all__ = (
    "DataRequired",
    "data_required",
    "Email",
    "email",
    "EqualTo",
    "equal_to",
    "IPAddress",
    "ip_address",
    "InputRequired",
    "input_required",
    "Length",
    "length",
    "NumberRange",
    "number_range",
    "Optional",
    "optional",
    "Regexp",
    "regexp",
    "URL",
    "url",
    "AnyOf",
    "any_of",
    "NoneOf",
    "none_of",
    "MacAddress",
    "mac_address",
    "UUID",
    "ValidationError",
    "StopValidation",
)

假如我们要写一个用户名的判断。

    username = StringField('username', validators=[data_required,
                  length(min=4, max=8,message='你的用户名必须大于4个字符,小于8个字符!')])

如果是一个密码的判断呢

    password=PasswordField('password',validators=[data_required,length(min=4, max=8,
                                                          message='你的密码必须大于4个字符,小于8个字符!')])                                                   

前端页面使用

你上面已经创建了wtform的表单类了,接下来将他返回给前端。

def user_login():
        user_form = UserForm()
        return render_template("user/login.html",user_form=user_form)

然后前端进行显示

<form method="POST" action="/">
{{user_form.password}}
    <input type="submit" value="Go">
</form>

就上面的password属性,他实际上就会变成表单标签input[password]
在这里插入图片描述
这里我们就完成了基本的wtform使用。

后台使用

创建user_form使用方法validate_on_submit() 来进行validate chain的判断,将所有错误存储到每个字段的erros列表中返回。

    user_form=UserForm()
        if user_form.validate_on_submit() is not True:
            return render_template("user/login.html",user_form=user_form)

CSRF

在我们运行的时候,有一个小插曲,他会爆csrf的错误,实际上,flask-wtform为我们封装了csrf protection,任何一个使用了FlaskForm的视图都会提前声明一个csrf protect,如果你使用的是ajax请求,他就不会去声明csrf保护,可以看到下面源码,他是去获取我们配置里面的secret_key
在这里插入图片描述
所以我们在配置中声明secret_key

    app.config['SECRET_KEY']='sdfgwfjoi23iosjdfi2'

介绍

csrf是什么呢,实际上csrf是一种web攻击,csrf全称是(Cross-site request forgery)跨站请求伪造,也就是跨域问题。他是一种对网站的恶意利用。
简单来说,就是攻击者通过一些技术手段,来使用已经有你的登录信息的浏览器进行访问并进行一系列操作。浏览器只能识别真实用户的浏览器,但并不能识别是不是真正的用户在操作浏览器。

在这里插入图片描述

自定义判断

在flask_wtform的实体类中新增方法,validate_<field_name>

    def validate_password(self,field):
        if self.data != '123':
            raise ValidationError('密码错误')
     self为Form表单对象,field为html标签对象。可以用field.data获取数据进行判断。发生错误之后返回ValidationError的异常。将error

自定义标签

上面我们演示的只是基础的出现html标签,那我们需要它的id或者class,或者增加新的属性怎么办。
我们可以用render_kw

    password=PasswordField('password',render_kw={'class':'login-input','placeholder':'请输入密码'},
                    validators=[data_required()])

文件上传

两个validation就足够文件上传,如果还想加声明

class FileForm(FlaskForm):
    avatar=FileField('image', validators=[
        FileRequired(),
        FileAllowed(['jpg', 'png'], '只能上传jpg和png后缀图片!')
    ])

captcha

就是真人验证,判断你是不是真人。如何使用呢?

在你的flaskform中引用:

class UserForm(FlaskForm):
    recaptcha = RecaptchaField()

前端页面

                {{ user_form.recaptcha }}

真实页面就会被注入
在这里插入图片描述
可以看到引入了一个js,一个div。但是因为我们在国内,网络无法访问google的api.js,所以无法使用这个。所以我们可以用pillow自己做一个图形验证码。

自定义验证码

建一个工具类

# 创建验证码工具类
import random

from PIL import Image, ImageFont, ImageDraw, ImageFilter

from apps.settings import Config


def get_random_color():
    color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
    return color


def create_captcha(length):
    size = (length * 25, 50)
    image = Image.new('RGB', size, get_random_color())
    # 获取ttf字体文件
    font = ImageFont.truetype(Config.BASH_DIR.join('resources/') + 'consola.ttf', size=40)
    # 将要从这里选择内容
    random_str = 'QWERTYqwertyASDFGasdfguioZXCVBzxcvbnm1234567890'
    # 真正的验证码
    real_str = ''
    draw = ImageDraw.Draw(image, 'RGB')
    for i in range(length):
        choice = random.choice(random_str)
        real_str += choice
        # 设置干扰线xy轴
        x0 = random.randint(0, 3)
        y0 = random.randint(0, 50)
        # x1 = random.randint(image.size[0]/2,image.size[0])
        y1 = random.randint(0, 50)
        # 设置干扰线
        draw.line([(x0, y0), (image.size[0], y1)], fill=get_random_color())
        # 设置每一个随机字
        draw.text(text=choice, fill=get_random_color(), font=font,
                  xy=(random.randint(5, 7) + i * 20, random.randint(3, 5)))
    #设置滤镜
    image=image.filter(ImageFilter.EDGE_ENHANCE)
    return image


flaskform中的recaptchaField改成string类型,并且将我们自定义的验证码发送到前端。

# 获取图形验证码
@user_bp.route("/get_captcha",methods=['get'])
def get_captcha():
    captcha = create_captcha(length=4)
    img_io = BytesIO()
    captcha.save(img_io, 'PNG')
    img_io.seek(0)
    # 使用flask自带的方法 send_file
    return send_file(img_io, mimetype='image/png')

前端直接地址接收就好。因为他直接返回二进制文件。

<img src='localhost:8080/user/get_captcha'/>

这个时候我们只完成了显示,我们还需要实现点击更换验证码。其实只需要通过js在后面加上一个随机数,让服务器知道这是另一个链接就好了。

function captcha(){
var img=document.getElementById('captcha')
img.src='/user/get_captcha?ra='+Math.random()
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值