Flask --WTF 处理表单

 表单

什么是表单?表单就是收集用户信息的各种表单元素的的集合区域,它的作用是实现用户和服务器的数据交互,通过表单收集客户端输入的数据信息。然后提交到站服务器端进行处理,Form表单是Web应用中最基础的一部分,为了能处理From 表单,Flask-wtf扩展提供了良好的支持。

 

1.使用Flask处理通用表单

说明:

Flask请求对象包含客户端发出的所有请求信息,其中request.form()能获取POST中提交表的数据,尽管Flask的请求对象提供的信息足够处理web的表单,但有些任务很单调,而且需要重复操作。

示列:

from flask import Flask,render_template,views,requestapp=Flask(__name__)@app.route('/login')
def login():if request.method=='GET': #如果访问为GET方法,返回应答信息。return '这是GET请求'else:return '这是POST请求'
@app.route('/')
def hello_word():return  render_template('index.html')
if __name__ == '__main__':app.run(debug=True)

创建一个渲染模块

用户名:
密码:

说明:

在上面的过程中,对表单没有进行必要的保护措施,很容易被人利用,控制用户在当前已经登录的Web 应用程序上执行非本意的操作,因此,在实际部署服务器上的代码时候不建议使用这个方式处理表单,推荐使用Flask-WTF方式处理表单。

1.1.Flask-WTF安装

pip  install flask-wtf

 

1.2启用CSRF启用

说明:

Flask-WTF提供了对所有From表单免受跨站请求伪造攻击的技术支持,通过动态的token令牌的方式。

import os
SECRET_KEY=os.urandom(24)    #生成SECRET_KEY(密钥)
CSRF_ENABLED=True   #开启CSRF保护

示列:

创建一个表单

from flask_wtf import Form   #引入基类
from wtforms import StringField,PasswordField  #引入From父类
from wtforms.validators import DataRequired    #引入From验证父类class MyForm(Form):name=StringField('name',validators=[DataRequired(message='这是在传递反馈的信息')])password = PasswordField('password', validators=[DataRequired(message='密码不能为空')])

创建一个py.文件


from flask import Flask,render_template,url_for,redirect
from form_wtf import MyForm
import config_s
app=Flask(__name__)
app.config.from_object(config_s)  #添加配置文件@app.route('/login',methods=('GET','POST'))
def login():form=MyForm()if form.validate_on_submit():   #将会检查是否是一个 POST 请求并且请求是否有效。return redirect(url_for('index'))   #如有有效就重定向到首页return render_template('rendering.html',form=form)   #form=form 这个一定要表明,需要把表传到渲染模块里面去@app.route('/')
def index():return '这是首页'if __name__ == '__main__':app.run(debug=True)

创建一个模块

{{ form.hidden_tag()}} {{ form.name(size=20) }}{{ form.password(size=20) }}

 2.使用Flask 上传文件

 

说明:

Flask 上传文件比较简单,需要注意以下三点

  • 一个
    标签被标记有enctype=multipart/form-data,并且在里面包含一个标签
  • 服务端应用通过请求对象上的file字典访问文件。
  • 使用文件save()方法将文件永久的保存在文件系统的某处。

示列:

from flask import Flask,render_template ,request
import os
import platform
from os import path
from werkzeug.utils import secure_filename
app=Flask(__name__)@app.route('/',methods=('GET','POST'))
def login():if request.method == 'GET':     #判断是否为GET请求return render_template('file_name.html')    #如果是就渲染这个模块else:f=request.files['file']   #获得文件流filename=secure_filename(f.filename)    #获得文件名字,中文会过滤f.save(path.join('static/uploads',filename))   #保存return '上传文件成功'if __name__ == '__main__':app.run(debug=True)

改进上传功能

  • 文件没有进行重新命名,多个用户可能会存在上传同名的文件。
  • 没有实现文件目录的自动创建,如果网站部署时候忘记创建文件保存目录,则会出现文件保存失败问题。
  • 文件上传时候,没有进行必要的文件格式的检验,用户可以直接将可执行文件上传到服务器上,影响到服务器数据的安全性。

from flask import Flask, render_template, request, send_from_directory
import time
import os
from os import path
from werkzeug.utils import secure_filename
import platform
from werkzeug.datastructures import CombinedMultiDict
from UploadForm import UploadForms
app = Flask(__name__)
if platform.system()=='Windows':   #判断是否是Windows系统slash='\\'                     #文件分隔符
else:platform.system()=='Linux'      #判断是否是Linux系统slash='/'
UPLOAD_PATH=os.path.curdir+slash+'uploads'+slash    #返回当前目录+分隔符+文件名+分隔符
@app.route('/',methods=('GET','POST'))
def index():if request.method=='GET':    #如果为GET请求就渲染下面这个模块return render_template('file_name.html')else:if not os.path.exists(UPLOAD_PATH):   #判断文件保存的路径是否存在os.makedirs(UPLOAD_PATH)     #没有就创建这个目录   os.mkdir()如果之前的目录不存在又要创建的会报错form=UploadForms(CombinedMultiDict([request.form,request.files]))   #把form和files组合起来if form.validate():   #进行验证f=request.files['file']  #获得文件流filename=secure_filename(f.filename)   # 获得文件名称ext=filename.rsplit('.',1)[1]"""#rsplit进行分割,返回的是个列表,通过索引取值jpg# 参数1指定的分隔符,参数2分割次数默认分割符出现的总次数"""print(ext)unix_time=int(time.time())  #获取时间戳print(unix_time)new_filename=str(unix_time)+'.'+ext   #对文件进行重新命名  时间戳+.+jpgfile_url=UPLOAD_PATH+new_filenameprint(file_url)f.save(path.join(UPLOAD_PATH,new_filename,))  #然后进行保存return '上传文件成功'else:return '只支持jpg,png,gif文件格式'@app.route('/images/',methods=('GET','POST'))
def get_image(filename):dirpath=os.path.join(app.root_path,'uploads')return send_from_directory(dirpath,filename)  #as_attachment=True 可以下载if __name__ == '__main__':app.run(debug=True)

 

from wtforms import Form,FileField,StringField
from wtforms.validators import InputRequired
from flask_wtf.file import  FileRequired,FileAllowed
class UploadForms(Form):file=FileField(validators=[FileRequired(),FileAllowed(['jpg','png','gif'])])

3.Cookie的使用

 

Cookie的基本使用

Flask中定义Cookie实际上就是在相应Rensponse的Set-Cookie字段中添加自定义的键值对,而获得Cookie ,就是在请求Response中通过键获取对应的值,所以在工程中必须引入Request和renspose模块。

设置Cookie主要有两种方法,一种是通过Response对象设置,另外一种是通过直接设置表单头来设置

1.1通过Response对象设置示列代码如下:

from flask import Flask,request,Responseapp=Flask(__name__)
@app.route('/')
def index():resp=Response('设置Cookie')resp.set_cookie('username','lgl',max_age=700000)"""ser_cookie(name,value,max_age,expire,path,domain, secure)max_age:设置到期时间以秒为单位name:规定cookie的名称value:规定Cookie 的值expire:设置过期时间,时间戳的形式path:规定在当前WEB下哪些目录有效果secure:是否通过安全的HTTPS来连接传输Cookiedomain:设置cookie的有效域名"""return resp
if __name__ == '__main__':app.run(debug=True)

1.2通过头部信息来设置cookie

from flask import Flask,request,Responseapp=Flask(__name__)
@app.route('/')
def index():resp=Response('设置Cookie')resp.headers['Set-Cookie']='username=lgls;Max-Age=700000;path=/'return resp
if __name__ == '__main__':app.run(debug=True)

1.3查看Cookie

from flask import Flask,request,Responseapp=Flask(__name__)
@app.route('/')
def index():resp=Response('设置Cookie')resp.headers['Set-Cookie']='username=lgls;Max-Age=700000;path=/'return resp@app.route('/get_cookie')
def get_cookie():username=request.cookies.get('username')print(username)return username
if __name__ == '__main__':app.run(debug=True)

1.4删除Cookie


from flask import Flask,request,Responseapp=Flask(__name__)
@app.route('/')
def index():resp=Response('设置Cookie')resp.headers['Set-Cookie']='username=lgls;Max-Age=700000;path=/'return resp@app.route('/get_cookie')
def get_cookie():username=request.cookies.get('username')print(username)return username@app.route('/del_cookie')
def del_cookie():resp=Response('删除cookie')resp.delete_cookie('username')return resp
if __name__ == '__main__':app.run(debug=True)

4.Session的使用

Session是基于Cookie实现的,保存在服务器的键值对中,在浏览器的Cookie中对应一个相同的随机字符产,用来再次请求的验证

因为Flask 的Session是通过加密之后放在Cookie中的,有加密就有密钥用于解密,用到了Flask的session模块就一定要配置SECRET_KEY这个全局宏,一般将SECRET_KEY设置为24位的字符

import os
from flask import Flask, session
app=Flask(__name__)
app.config['SECRET_KEY']=os.urandom(24)   #  密钥  ---进行随机输出24个随机字符
@app.route('/')
def set_session():session['username']='liangguolong'   #设置sessionreturn 'session设置成功'
@app.route('/get_session')      #获取session
def get_session():username=session.get('username')return username or '为空'
@app.route('/pop_session')
def pop_session():session.pop('username')   """session.pop()是删除指定的session.clear是删除所有的"""return '删除成功'if __name__ == '__main__':app.run(debug=True)

1.1设置Session的过期时间

如果没有指定Session的过期时间,那么默认浏览器会在关闭过后自动结束。session.permanent=True 那么过期时间为31天。

可以通过datetime来指定Session 失效的时间

@app.route('/')
def set_session():session['username']='liangguolong'   #设置sessionsession.permanent=True      #来设置时间为1个月return 'session设置成功'
from datetime import timedelta
from flask import Flask, session
app=Flask(__name__)app.config['SECRET_KEY']=os.urandom(24)   #  密钥  ---进行随机输出24个随机字符
app.config['PERMANENT_SESSION_LIFETIME']=timedelta(days=7)   #可以设置指定天数
@app.route('/')
def set_session():session['username']='liangguolong'   #设置sessionsession.permanent=True      #来设置时间为1个月return 'session设置成功'

5.钩子函数

根据需要,有时候需要在正常执行代码的前中后期强行执行一段我们想要执行的代码,实现这种函数的功能函数就要叫做钩子函数,钩子函数的实质是用特定的装饰器函数

from flask import Flask,session,render_template
app=Flask(__name__)
@app.before_first_request
def first_request():print('我是第一')
@app.before_request
def before_request():print('我每次请求之前都会调用我')@app.after_request
def after_request(f):""":f为一个response对象return f 需要返回一个response对象,可以是新的,也可以是传入进入的"""print('每次请求之后会调用我')return f
@app.teardown_appcontext
def teardown_appcontext(e):"""注册在每一个请求的末尾,不管是否有异常,每次请求的最后都会执行。:param e:"""print('注册在每一个请求的末尾,不管是否异常')return e
@app.template_filter('uuuper')
def template_filter(s):"""自定义过滤器上面uuuper就是过滤器名称,在模板中使用,例如{{username}uuuper}}就是把字符串全部大写:param s: 传入进来的参数,可以有多个,根据你要的功能添加:return: 返回处理后的数据"""print('自定义过滤器')return s.upper()
@app.context_processor
def context_processor():"""返回一个字典,字典中的值在模板任意地方都能使用,该函数被调用时在before_request之后after_request之前:return: 携带了需要的数据的字典"""print('context_processor')context = {}username = session.get('username')context.update(username=username)return context
@app.errorhandler(404)
def errorhandler(e):"""发生请求错误时, 框架会自动调用相对钩子函数, 并向钩子函数传入error参数异常处理,可以根据不同的异常定制不同的处理方法:param e: 异常信息:return: 可以返回一个模板,例如404.html,告知用户错误信息等"""print('error_handler,404')print(e)return render_template('index.html'), 404
@app.route('/')
def index():print('-------123----')return '这是首页'if __name__ == '__main__':app.run(debug=True)

 

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部