在开发flask项目的时候,难免会遇到文件传输的需求,现在就以上传用户头像为例,说一下在flask中文件如何上传。
python 3.7
flask 2.0.2
本篇博客代码接着上一篇博客flask使用redis继续写,项目目录如下
因为现在要添加头像,所以模型类也要添加对应字段。
models.py
from . import db
class Test(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(10))
password = db.Column(db.String(20))
sex = db.Column(db.String(2))
avatar_url = db.Column(db.String(256))
# 将用户对象转换为字典并返回
def to_dict(self):
test_dict = {
'id': self.id,
'name': self.name,
'sex': self.sex,
'avatar_url': self.avatar_url
}
return test_dict
然后输入如下命令将更改更新到数据库:
python manage.py db migrate
python manage.py db upgrade
在上面我增加了性别,所以注册视图和模板要做相应的修改
flask_teach/test/views.py
from flask import request, render_template, redirect, session, url_for, jsonify, current_app
from . import test_blue
from flask_teach import db, models, redis_store
# 引入装饰器
from flask_teach.decorators import decorator_login
from flask_teach.common import random_num
# 注册视图
@test_blue.route('/register', methods=['POST', 'GET'])
def register():
# 根据请求方式的不同返回不同结果
if request.method == 'GET':
return render_template('test/register.html')
else:
name = request.form['name']
password = request.form['password']
sex = request.form['sex']
# 不能注册名字相同的用户
user = models.Test.query.filter_by(name=name).first()
if user:
return "该用户已存在"
# 创建实例对象,默认用户性别为男
test = models.Test(name=name, password=password, sex=sex)
# 保存到数据库,在config配置里面设置了自动提交,所以在这里不用再次提交
db.session.add(test)
# db.session.commit() # 没设置自动提交要加这句
return "注册成功!!!"
register.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册title>
head>
<body>
<form action="/test/register" method="post">
用户名:<input type="text" name="name"><br>
密码:<input type="password" name="password"><br>
性别:<input type="radio" name="sex" checked value="男">男
<input type="radio" name="sex" value="女">女
<br>
<input type="submit" value="注册">
form>
body>
html>
用户头像上传是在用户信息里面上传,所以要编写一个用户信息视图。
flask_teach/test/views.py
# 更新用户信息
from flask import request, render_template, redirect, session, url_for, jsonify, current_app
from . import test_blue
from flask_teach import db, models, redis_store
# 引入装饰器
from flask_teach.decorators import decorator_login
from flask_teach.common import random_num
......
# 用户信息视图
@test_blue.route('/user_message', methods=['GET', 'POST'])
@decorator_login
def user_update():
# 获取用户名
name = session.get('name')
# 获取用户对象
user = models.Test.query.filter_by(name=name).first()
# 将用户对象装换成用户字典
user_dict = user.to_dict()
# 根据请求方式不同做出不同的响应
if request.method == 'GET':
return render_template('test/user_message.html', user=user_dict)
else:
name = request.form['name']
sex = request.form['sex']
avatar = request.files.get('avatar')
# 如果上传了头像才保存和更新数据库的头像信息
if avatar:
# 设置头像存储路径
absolute_avatar_path = current_app.static_folder + '/avatar/{}.png'.format(name)
# 保存图片
with open(absolute_avatar_path, 'wb+') as f:
f.write(avatar.read())
f.close()
user.avatar_url = absolute_avatar_path
# 更新用户信息
user.name = name
user.sex = sex
# 更新session的name
session['name'] = name
# 将更新后的对象装换成字典
user_dict = user.to_dict()
# 返回更新结果
return render_template('test/user_message.html', user=user_dict)
编写模板 user_message.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户信息title>
<script src="../../static/js/jquery-3.6.0.min.js">script>
<style>
img {
width: 100px;
height: 100px;
}
style>
head>
<body>
<img src="/test/user_avatar" alt="" id="avatar_img">
<form action="/test/user_message" enctype="multipart/form-data" method="post">
用户头像:<input type="file" name="avatar" id="avatar"><br>
用户名:<input type="text" value="{{user.name}}" name="name"><br>
性别:
{% if user.sex== '男' %}
<input type="radio" value="男" checked name="sex">男
<input type="radio" value="女" name="sex">女
{% else %}
<input type="radio" value="男" name="sex">男
<input type="radio" value="女" checked name="sex">女
{% endif %}
<br>
<input type="submit" value="提交">
form>
<a href="/test/index">返回首页a>
<script>
$(function () {
// 头像预览
$('#avatar').change(function () {
// 1.创建文件阅读器对象
let avatar_img = new FileReader()
// 2.获取用户上传的文件对象
let up_avatar = $(this)[0].files[0];
// 3.将文件对象交给阅读器对象解析
avatar_img.readAsDataURL(up_avatar)
// 4.等待文件阅读器加载完毕,利用文件阅读器将文件展示到前端页面,修改src属性,
// avatar_img.result 获取图像路径
avatar_img.onload = function () {
$('#avatar_img').attr('src', avatar_img.result)
}
})
})
script>
body>
html>
前端发送获取文件的请求时,服务器要返回对应文件,因此在这里专门编写一个返回用户头像的视图
flask_teach/test/views.py
from flask import request, render_template, redirect, session, url_for, jsonify, current_app
from . import test_blue
from flask_teach import db, models, redis_store
# 引入装饰器
from flask_teach.decorators import decorator_login
from flask_teach.common import random_num
# 返回用户头像
@test_blue.route('/user_avatar')
def user_avatar():
name = session.get('name')
# 获取用户
user = models.Test.query.filter_by(name=name).first()
# 如果用户头像不存在,则返回默认头像
# current_app.send_static_file("文件路径") 能返回静态文件夹里面的文件
if not user.avatar_url:
if user.sex == '男':
return current_app.send_static_file('avatar/male.jpeg')
if user.sex == '女':
return current_app.send_static_file('avatar/female.jpeg')
# 头像存在,则正常返回
return current_app.send_static_file('avatar/{}.png'.format(name))
注册之后登录查看用户信息
更改信息后点提交
可以看到数据已经更新,后台也保存了对应图片
大功告成!!!有什么问题欢迎在评论区留言。
所有代码已经传到了码云上https://gitee.com/li_weiyan/flask_teach.git,有兴趣的可以看一下。