一、原生表单
1. 添加模板文件login.html,内容如下:
<form method="post" action="{{ url_for('check') }}">
用户名:<input name="username" type="text" />
<input type="submit" value="立即登录" />
</form>
2. 视图函数,如下:
# 登录
@app.route('/login/')
def login():
return render_template('login.html')
P
# 校验
@app.route('/check/', methods=['POST'])
def check():
print(request.form.get('username'))
return 'Hello %s !' % request.form['username']
3. 将登录页面和校验的路由合并,如下:
@app.route('/login/', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
return 'Hello %s !' % request.form['username']
一个路由处理时,表单的action属性不用书写,默认提交到当前路由。
二、flask-wtf处理表单
说明:flask-wtf是一个用于表单处理的扩展库,提供了CSRF、校验等功能,使用非常方便
1.跨站请求伪造保护(csrf)
Flask-WTF 能保护所有表单免受跨站请求伪造(Cross-Site Request Forgery,CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站时就会引发 CSRF 攻击。为了实现 CSRF 保护,Flask-WTF 需要程序设置一个密钥。Flask-WTF 使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。
#视图中 设置 Flask-WTF
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'#字典可用来存储框架、扩展和程序本身的配置变量。
#为了增强安全性,密钥不应该直接写入代码,而要保存在环境变量中。
#模板中使用
{{ form.hidden_tag() }} #或 {{ form.csrf_token }}
2.关闭csrf
@app.route('/form/',methods=['post','get'])
def newform():
form = NameForm(csrf_enabled = False)
3.flask-wtf常见字段类型和验证器
常见字段类型
字段类型 | 说明 |
---|---|
StringField | 普通文本字段 |
SubmitField | 提交按钮 |
PasswordField | 密码文本字段 |
HiddenField | 隐藏文本字段 |
TextAreaField | 多行文本字段 |
DateField | 文本字段,datetime.date格式 |
DateTimeField | 文本字段,datetime.datedatime格式 |
IntegerField | 文本字段,值为整数 |
FloatField | 文本字段,值为小数 |
BooleanField | 复选框,值为True或False |
RadioField | 单选框 |
SelectField | 下拉框 |
FileField | 文件上传 |
常见验证器类
验证器 | 说明 |
---|---|
DataRequired | 确保字段有值 必填项 |
邮箱地址 验证邮箱 | |
IPAddress | IP地址 |
Length | 规定字符长度 有min和max两个值进行限制。 |
NumberRange | 输入数值的范围 |
EqualTo | 验证两个字段的一致性 |
URL | 有效的URL |
Regexp | 正则验证 |
info = TextAreaField('个人信息',render_kw={'style':'resize:none;'}) #render_kw 给当前的标签添加属性
表单类
每个 Web 表单都由一个继承自Form的类表示。这个类定义表单中的一组字段(表单的内容与类的字段是一一对应的),每个字段都用对象(表单中的对象)表示。字段对象可附属一个或多个验证函数。
4.定义表单类
# 导入表单基类
from flask_wtf import FlaskForm
# 导入字段类型
from wtforms import StringField, SubmitField
# 导入验证器类
from wtforms.validators import DataRequired #必填字段
# CSRF需要使用
app.config['SECRET_KEY'] = '123456'
# 定义表单类
class NameForm(FlaskForm):
#name 为表单的name名称
name = StringField('用户名', validators=[DataRequired()])
submit = SubmitField('提交')
5.添加视图函数:
@app.route('/')
def index():
# 创建表单对象
form = NameForm()
# 分配到模板中进行渲染
return render_template('form.html', form=form)
6.模板文件中渲染表单:
Form
类有一个 hidden_tag
方法, 它在一个隐藏的 DIV 标签中渲染任何隐藏的字段,包括 CSRF 字段:
{# 原生渲染 #}
<form>
{# CSRF的隐藏字段 #}
{{ form.hidden_tag() }} #或 {{ form.csrf_token }}
{# name字段,可以指定id、class等属性,定制显示效果 style='color:red 设置文本颜色 #}
{{ form.name.label() }}{{ form.name(id='xxx', class='yyy',style='color:red) }}
{{ form.name.errors }} #错误提示
{# submit字段 #}
{{ form.submit() }}
</form>
7.在视图中使用bootstrap的wtf快速渲染表单
#使用bootstrap快速渲染 其它代码不变
from flask_bootstrap import Bootstrap
app.config['BOOTSTRAP_SERVE_LOCAL'] = True #加载本地的js文件
bootstrap = Bootstrap(app)
{% extends 'bootstrap/base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{{ wtf.quick_form(form) }}
模板中
更改表单提交地址和表单排列样式
wtf.quick_form(form,form_type='horizontal',action= url_for('login') )
查看都有哪些参数可以查看 wtf.html 里面的 quick_form 宏
{# bootstrap渲染 #}
{% extends 'bootstrap/base.html' %}
{# 导入渲染工具 #}
{% import 'bootstrap/wtf.html' as wtf %}
{# 渲染表单 调用宏方法 wtf.quick_form#}
{% block content %}
<div class="container">{{ wtf.quick_form(form,action=url_for('upload')) }}</div>
{% endblock %}
8.表单校验
@app.route('/', methods=['GET', 'POST'])
def index():
# return '表单使用'
name = None
# 创建表单对象
form = NameForm()
# 表单校验
#validate_on_submit 会便捷地检查该请求是否是一个 POST 请求以及是否有效。
if form.validate_on_submit():
name = form.name.data
form.name.data = ''
# 分配到模板中进行渲染
return render_template('form.html', form=form, name=name)
9.自定义表单验证器
自定义字段验证:就是写一个validate_字段名'的函数,如下:
# 定义表单类
class NameForm(FlaskForm):
name = StringField('用户名', validators=[DataRequired()])
submit = SubmitField('提交')
#如果字段中也存在Length对象的验证 那么这俩个验证会重复叠加
#userName = StringField('用户名',validators=[DataRequired(),Length(3, 6, message='请输入正确的长度')])
# 自定义字段验证函数,格式是写一个'validate_字段名'的函数
def validate_name(self, field):
if len(field.data) < 6:
raise ValidationError('用户名长度不能少于6个字符')
10.所有的字段和验证器的使用
class Form(FlaskForm):
hidde = HiddenField()
username = StringField('用户名')
userpass = PasswordField('密码')
confirm = PasswordField('确认密码',validators=[EqualTo('userpass',message='密码和确认密码不一致')])
info = TextAreaField('个人信息',render_kw={'style':'resize:none;'})
birth = DateField('出生年月',format='%Y/%m/%d')
birthday = DateTimeField('生日日期')
age = IntegerField('age',validators=[NumberRange(min=6,max=99,message='年龄范围6~99')])
money = FloatField('money')
rember = BooleanField('记住我')
sex = RadioField('sex',choices=[('m','男'),('w','女')])
address = SelectField('address',choices=[('1001','北京'),('1002','上海'),('1003','深圳')])
photo = FileField('photo')
email = StringField('email',validators=[Email(message='请输入合法的邮箱地址')])
ip = StringField('ip',validators=[IPAddress(message='输入合法的ipv4地址')])
url = StringField('url',validators=[URL(message='请输入正确的url')])
phone = StringField('手机号码',validators=[Regexp("[1][3-8][0-9]{9}$",flags=re.I|re.M|re.S,message='输入正确的手机号码')])
# re.I 不区分大小写
# re.S 使.匹配换行符
# re.M 改变 ^ 和 $ 作用 使之可以多行匹配
submit = SubmitField('submit')
#自定义表单验证器 validate_ 死的 + 验证的属性名 当点击的时候 就会执行当前的自定义表单验证器
def validate_username(self,field):
if self.username.data == 'zhangsan':
raise ValidationError('当前用户已存在')
评论 (0)