1. 上传、访问文件
- 上传文件的步骤:
- 在模版html中,表单需要指定
encotype='multipart/form-data'
才能上传文件。 - 在后台如果想要获取上传的文件,那么应该使用
request.files.get('文件名')
来获取。 - 保存文件之前,先要使用
werkzeug.utils.secure_filename
来对上传上来的文件名进行一个过滤。能保证不会有安全问题。 - 获取到上传上来的文件后,使用
文件对象.save(路径)
方法来保存文件。路径=完整路径=路径名+文件名
- 在模版html中,表单需要指定
- 【upload.html页面】
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>头像:</td>
<td><input type="file" name="pichead"></td>
</tr>
<tr>
<td>描述:</td>
<td><input type="text" name="desc"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
- 【app.py文件】
from flask import Flask,request,render_template
import os
from werkzeug.utils import secure_filename
app = Flask(__name__)
UPLOAD_PATH = os.path.join(os.path.dirname(__file__),'images')
@app.route('/upload/',methods=['GET','POST'])
def upload():
if request.method == 'GET':
return render_template('upload.html')
else:
desc = request.form.get("desc")
pichead = request.files.get("pichead")
filename = secure_filename(pichead.filename) #包装一下 保证文件安全
# pichead.save(os.path.join(UPLOAD_PATH,pichead.filename)) #可优化
pichead.save(os.path.join(UPLOAD_PATH,filename)) #已优化
print(desc)
return '文件上传成功'
if __name__ == '__main__':
app.run(debug=True)
- 访问文件:从服务器上读取文件,应该定义一个url与视图函数,来获取指定的文件。在这个视图函数中,使用
send_from_directory(文件的目录,文件名)
来获取。
from flask import Flask
import os
from flask import send_from_directory
app = Flask(__name__)
UPLOAD_PATH = os.path.join(os.path.dirname(__file__),'images')
@app.route('/images/<filename>/')
def get_image(filename):
return send_from_directory(UPLOAD_PATH,filename)
if __name__ == '__main__':
app.run(debug=True)
2. 利用flask_wtf验证上传的文件
- 关键点:
-
定义验证表单类的时候,对文件类型的字段,需要采用
FileField
这个类型,即wtforms.FileField。 -
验证器需要从
flask_wtf.file
中导入。flask_wtf.file.FileRequired
和flask_wtf.file.FileAllowed
-
flask_wtf.file.FileRequired
是用来验证文件上传不能为空。 -
flask_wtf.file.FileAllowed
用来验证上传的文件的后缀名, 如常见图片后缀 .jpg 和.png以及.gif等。 -
在视图函数中,需要使用
from werkzeug.datastructures import CombinedMultiDict
来把request.form
与request.files
来进行合并。 -
最后使用 表单验证对象.validate()进行验证。
-
代码如下
【upload.html页面】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>头像:</td>
<td><input type="file" name="pichead"></td>
</tr>
<tr>
<td>描述:</td>
<td><input type="text" name="desc"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
【formscheck.py文件】
from wtforms import Form,FileField,StringField
from wtforms.validators import InputRequired
# flask_wtf
from flask_wtf.file import FileRequired,FileAllowed
class UploadForm(Form):
pichead = FileField(validators=[FileRequired(),FileAllowed(['jpg','png','gif'])])
desc = StringField(validators=[InputRequired()])
【app.py文件】
from flask import Flask,request,render_template
import os
from werkzeug.utils import secure_filename
from formscheck import UploadForm
from werkzeug.datastructures import CombinedMultiDict
app = Flask(__name__)
UPLOAD_PATH = os.path.join(os.path.dirname(__file__),'images')
#利用flask-wtf验证上传的文件
@app.route('/upload/',methods=['GET','POST'])
def upload():
if request.method == 'GET':
return render_template('upload.html')
else:
form = UploadForm(CombinedMultiDict([request.form,request.files]))
if form.validate():
# desc = request.form.get("desc")
# pichead = request.files.get("pichead")
desc = form.desc.data
pichead = form.pichead.data
filename = secure_filename(pichead.filename)
pichead.save(os.path.join(UPLOAD_PATH,filename))
print(desc)
return '文件上传成功'
else:
print(form.errors)
return "文件上传失败"
if __name__ == '__main__':
app.run(debug=True)
3. 示例
【33_wtforms_demo.py】
from flask import Flask,request,render_template,session,send_from_directory
from formscheck import RegisterForm,RegisterForm2,CreateForm,UploadForm
from werkzeug.utils import secure_filename
from werkzeug.datastructures import CombinedMultiDict
import os
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
UPLOAD_PATH=os.path.join(os.path.dirname(__file__),"images") # D:\python_project\33_wtforms_demo\images
@app.route('/')
def hello_world():
return 'Hello World!'
# wtforms表单验证的基本使用
@app.route('/register/',methods=['GET','POST'])
def register():
if request.method == 'GET':
return render_template('register.html')
else:
# 使用表单验证对象进行验证
form = RegisterForm(request.form)
if form.validate(): # 验证;要么ok;要么no
return "验证通过"
else:
print(form.errors)
return "数据验证通不过"
import random
# wtforms常用验证器使用
@app.route('/register2/',methods=['GET','POST'])
def login():
if request.method == 'GET':
# 自定义验证器 实现验证码验证
code = random.randint(1000,9999) # 生成一个随机4位整数值的验证码
session['code'] = str(code)
return render_template("register2.html")
else:
form = RegisterForm2(request.form)
if form.validate():
return "验证OK"
else:
print(form.errors)
return "验证失败"
import uuid
print(uuid.uuid4())#edbfa1d6-28f2-4f40-9111-528141a8e77d
# WTForms渲染模版 了解
@app.route('/createform/')
def createform():
form = CreateForm()
return render_template('create_form.html',form=form)
################ 上传、访问文件 ################
# flask 上传文件的实现
# @app.route('/upload/',methods=['GET','POST'])
# def upload():
# if request.method == 'GET':
# return render_template('upload.html')
# else:
# desc = request.form.get("desc")
# pichead = request.files.get("pichead")
# print(desc)
# #保存到服务器 #D:\python_project\33_wtforms_demo\images
# filename = secure_filename(pichead.filename) #对pichead.filename文件做一下 包装 保证文件名更安全
# # pichead.save(os.path.join(UPLOAD_PATH,pichead.filename)) #文件名处可优化
# pichead.save(os.path.join(UPLOAD_PATH,filename)) #已优化
# return '文件上传成功'
# 访问服务器上(已经上传成功)的图片
@app.route('/images/<filename>/')
def get_image(filename):
return send_from_directory(UPLOAD_PATH,filename)
# 利用flask-wtf验证上传的文件
@app.route('/upload/',methods=['GET','POST'])
def upload():
if request.method == 'GET':
return render_template('upload.html')
else:
form = UploadForm(CombinedMultiDict([request.form,request.files]))
if form.validate():
# desc = request.form.get("desc")
# print(type(request.form))
# pichead = request.files.get("pichead")
# 从form对象里边获取 desc 和pichead数据
pichead =form.pichead.data
print(pichead.filename) # 获取上传的文件名
print(form.desc.data)
# print(desc)
# 保存到服务器 #D:\python_project\33_wtforms_demo\images
filename = secure_filename(pichead.filename) # 对pichead.filename文件做一下 包装 保证文件名更安全
# pichead.save(os.path.join(UPLOAD_PATH,pichead.filename)) #文件名处可优化
pichead.save(os.path.join(UPLOAD_PATH, filename)) # 已优化
return '文件上传成功'
else:
print(form.errors)
return "上传文件失败" # 不符合图片格式要求
if __name__ == '__main__':
app.run(debug=True)
# 工具类
from wtforms import Form,StringField,IntegerField,RadioField,BooleanField,SelectField,TextAreaField,DateField,FileField
from wtforms.validators import Length,EqualTo,Email,InputRequired,NumberRange,Regexp,URL,UUID,ValidationError
from flask import session
# 利用flask-wtf 验证上传的文件
from flask_wtf.file import FileRequired,FileAllowed
# 定义一个表单验证类
class RegisterForm(Form):
uname = StringField( validators=[Length(min=2,max=15,message="用户名的长度必须是2-15之间")])
pwd = StringField(validators=[Length(min=6, max=12)])
pwd2 = StringField(validators=[Length(min=6,max=12),EqualTo("pwd",message="两次输入密码不一致")])
# 定义一个表单验证类2
class RegisterForm2(Form):
email = StringField(validators=[Email()])
uname = StringField(validators=[InputRequired()])
age = IntegerField(validators=[NumberRange(min=18,max=40)])
phone = StringField(validators=[Regexp(r'1[34578]\d{9}')])
phomepage = StringField(validators=[URL()])
uuid = StringField(validators=[UUID()])
code = StringField(validators=[Length(min=4,max=4)])
# 光有长度验证 不能满足验证码验证需求,此时需要自定义验证器来对 某字段验证进行强化
def validate_code(self,field):
# 去字段field对象上的值来做验证
print(field.data,session.get('code'))
scode = session.get('code')
if field.data != scode:
raise ValidationError(message='输入的验证码不一致!!')
# wtforms 渲染模版的定义
class CreateForm(Form):
# uname = StringField(validators = [InputRequired()])
uname = StringField("用户名:",validators = [InputRequired()])
age = IntegerField("年龄:",validators = [NumberRange(18,40)])
remember = BooleanField("记住我:")
addr = SelectField('地址:',choices=[('bj',"北京"),('sj','上海'),('tj','天津')])
################ 上传、访问文件 ################
# 验证上传的文件类型
class UploadForm(Form):
pichead = FileField(validators=[FileRequired(),FileAllowed(["jpg","png","gif"])])
desc = StringField(validators=[InputRequired()])
【upload.html】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>头像:</td>
<td><input type="file" name="pichead"></td>
</tr>
<tr>
<td>描述:</td>
<td><input type="text" name="desc"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>