flask上传文件


前言

在开发flask项目的时候,难免会遇到文件传输的需求,现在就以上传用户头像为例,说一下在flask中文件如何上传。


一、环境

python 3.7
flask 2.0.2

二、使用

本篇博客代码接着上一篇博客flask使用redis继续写,项目目录如下
在这里插入图片描述

1.更新模型类

因为现在要添加头像,所以模型类也要添加对应字段。
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

2.更改视图和模板

在上面我增加了性别,所以注册视图和模板要做相应的修改
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>

3.编写视图

用户头像上传是在用户信息里面上传,所以要编写一个用户信息视图。
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,有兴趣的可以看一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值