说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!
接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/86247891
目录
一丶构建一个用于验证登录状态的装饰器
二丶七牛云的使用
三丶上传头像后端编写
四丶上传头像前端编写
五丶修改用户名后端编写
六丶修改用户名前端编写
七丶在我的爱家上,显示头像用户名以及手机号
八丶最终效果动图
一丶构建一个用于验证登录状态的装饰器
1.因为这个装饰器用的地方比较多,所以就在项目中的utils目录下的commons模块中进行定义
def login_required(view_func):
"""
验证登录状态的装饰器
:param view_func: 需要装饰的视图函数
:return:
"""
def wrapper(*args, **kwargs):
pass
2.获取session中用户id
user_id = session.get("user_id")
3.根据user_id来判断用户登录状态,如果user_id不为空,说明用户已经登录,那么就执行视图函数,否则返回对应错误信息
if user_id is not None:
return view_func(*args, **kwargs)
else:
return jsonify(errno=RET.SESSIONERR, errmsg="用户未登录")
4.通过flask中的g对象来保存将来在视图函数中要用的user_id
g.user_id = user_id
5.导入python标准库functools,见名知义,就是函数工具库,这个库有个wraps方法,用于作为在闭包中的内置函数的装饰器,意义就是不会改变函数使用装饰前的特性(建议再定义装饰器时,在内置函数上添加@functools.wraps()装饰器)
@functools.wraps(view_func)
def wrapper(*args, **kwargs):
二丶七牛云的使用
1.图片存储服务---七牛云
- step1 在https://portal.qiniu.com/signup 进行注册
- step2 注册成功后,添加进入对象存储
- step3 新建存储空间,如下图所示(需要实名认证审核期为三天)
创建成功后,1个月的测试使用期限
- step4 进入文档中心----》选择SDK&工具----》官方SDK----》找到Python(服务端),点击文档说明,有案列以及安装方法
- step5 查看官网提供的上传图片案列
# -*- coding: utf-8 -*-
# flake8: noqa
from qiniu import Auth, put_file, etag
import qiniu.config
#需要填写你的 Access Key 和 Secret Key
access_key = 'Access_Key'
secret_key = 'Secret_Key'
#构建鉴权对象
q = Auth(access_key, secret_key)
#要上传的空间
bucket_name = 'Bucket_Name'
#上传到七牛后保存的文件名
key = 'my-python-logo.png'
#生成上传 Token,可以指定过期时间等
token = q.upload_token(bucket_name, key, 3600)
#要上传文件的本地路径
localfile = './sync/bbb.jpg'
ret, info = put_file(token, key, localfile)
print(info)
assert ret['key'] == key
assert ret['hash'] == etag(localfile)
- step6 Access_Key以及Secret_Key在个人面板-----》密匙管理里进行查看
2.在项目utils目录下创建一个image_storage.py文件,用于我们作进一步的封装
- step1 将案列代码拷贝到该py文件中,填写access_key和secret_key,以及要上传的空间名bucket_name
- step2 不设定key上传到七牛上的文件名,即设定key变量的值为None
- step3 通过导入的qiniu库,查看qiniu/init中除了案列中import的put_file方法(通过文件名上传),还有另外一个put_data方法(通过文件二进制流上传),我们使用put_data方法,这样直接从本地通过with open read方法直接将图片读取出来的二进制数据上传到七牛
- step4 修改代码,不使用put_file方法,使用put_data方法
ret, info = put_data(token, None, localfile)
- step5 封装代码到storage方法中
- step6 通过with open read方式读取image_storage文件同路径下的1.jpg图片,调用storage方法将读取的二进制内容传给此方法
if __name__ == '__main__':
with open("./1.jpg","rb") as f:
file_data = f.read()
storage(file_data)
3.测试七牛云接口,进行图片上传
- step1 运行程序,查看打印的ret的值和info的值,状态码200就表示上传成功,hash值顾名思义使用hash转换后的值,因为程序中注释掉了key文件名,所以七牛云就将hash值当作了key值
- step2 回到七牛云上,刷新页面,进入存储空间中的内容管理,就能看到我们刚上传的图片了,这里图片名字就是程序运行结果中的hash值
- step3 浏览器中打开新的标签,将域名+/+文件名中间以/分割,拼接到一起,粘贴到标签地址栏中,回车则可以查看该我们上传的图片了
三丶上传头像后端编写
1.在api_1.0目录下创建profile.py文件,用于作个人信息逻辑编辑
2.在init文件中导入此py文件
from . import verify_code, passport, profile
3.定义视图函数以及路由规则
@api.route("/users/avatar", methods=["POST"])
def set_user_avatar():
"""
上传头像图片
:param image user_id
:return:
"""
pass
4.导入之前定义的验证登录状态的装饰器
from ihome.utils.commons import login_required
5.编写业务逻辑
- step1 获取用户id
user_id = g.user_id
- step2 获取图片
image_file = request.files.get("avatar")
- step3 判断用户是否上传图片
if image_file is None:
return jsonify(errno=RET.PARAMERR, errmsg="未上传图片")
- step4 读取图片二进制数据
image_data = image_file.read()
- step5 修改image_storage文件,当状态码为200时,返回key值,不为200时表示上传失败,返回异常
if info.status_code == 200:
"""表示图片上传成功"""
return ret.get("key")
else:
# 上传失败
raise Exception("图片上传七牛云失败")
- step6 回到profile中,调用封装好的七牛接口上传图片,返回文件名
try:
file_name = storage(image_data)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.THIRDERR, errmsg="上传图片失败")
- step7 将图片地址保存到数据库avatar_url字段,思考,需要将域名与文件名拼接好后保存,还是只保存文件名,为了节省空间,并且只有文件名不同,所以执行保存文件名到数据库avatar_url字段即可
try:
User.query.filter_by(id=user_id).update({"avatar_url":file_name})
db.session.commit()
except Exception as e:
db.session.rollback()
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="保存图片信息失败")
- step8 拼接图片完整链接
avatar_url = constants.QINIU_URL_DOMAIN + file_name
- step9 保存成功后,返回给前端正确响应
return jsonify(errno=RET.OK, errmsg="保存成功", data={"avatar_url": avatar_url})
四丶上传头像前端编写
1.前端个人信息HTML代码(不展示)
2.前端个人信息JS代码(不展示)
3.修改profile.html代码,将id="form-avatar"的表单中的action="/api/profile/avatar" method="post"去掉,通过导入的jquery.form.min.js插件来发送表单数据
4.在profile.js中进行如下编写
- step1 阻止表单默认行为
$(document).ready(function () {
$('#form-avatar').submit(function (e) {
// 阻止表单默认行为
e.preventDefault();
})
});
- step2 利用jquery.form.min.js插件通过的ajaxSubmit对表单进行异步提交
$(this).ajaxSubmit({
url:"/api/v1.0/users/avatar",
type:"post",
dataType:"json",
headers:{
"X-CSRFToken": getCookie("csrf_token")
},
success: function (resp) {
if (resp.errno == "0"){
// 上传成功
var avatarUrl = resp.data.avatar_url;
$('#user-avatar').attr("src", avatarUrl)
}else {
alert(resp.errmsg);
}
}
})
5.测试
- step1 运行项目
python manage.py runserver
- step2 输入http://127.0.0.1:5000 主页进行登录,然后进入个人信息,点击修改,选择头像点击上传后,如下图所示
- step3 查看七牛云内容管理
五丶修改用户名后端编写
1.创建视图函数以及定义路由接口
@api.route("/users/name", methods=["POST"])
@login_required
def update_name():
pass
2.逻辑编写,当用户输入昵称后,点击保存,向后端接口发送请求,携带用户填写的昵称name,以json格式发送数据,然后在后端获取name,并通过用户id,数据库操作更新name字段的值为用户输入的昵称name
- step1 获取用户id
user_id = g.user_id
- step2 获取前端发送过来的参数
req_dict = request.get_json()
name = req_dict.get("name")
- step3 判断用户是否输入用户名
# 判断用户是否输入用户名
if name is None:
return jsonify(errno=RET.NODATA, errmsg="昵称不能为空")
- step4 判断昵称是否存在
try:
user = User.query.filter_by(id=user_id).first()
# 从数据中获取用户昵称
user_name = user.name
if user_name is not None and user_name == name:
return jsonify(errno=RET.DATAEXIST, errmsg="用户名已存在")
except Exception as e:
current_app.logger.error(e)
- step5 将用户输入的name昵称保存到数据库中
try:
User.query.filter_by(id=user_id).update({"name": name})
db.session.commit()
except Exception as e:
db.session.rollback()
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="保存用户昵称失败")
- step6 最后返回正确响应
return jsonify(errno=RET.OK, errmsg="修改成功", data={"name": name})
六丶修改用户名前端编写
1.前端个人信息HTML代码(不展示)
2.前端个人信息JS代码(不展示)
3.去掉profile.html中action="/api/profile/name" method="post"
4.在profile.js中添加脚本,当点击保存时,触发id = form-name的submit回调函数,发送users/name地址调用update_name是视图函数,将构造用户填写的name通过ajax方式传给后端,来完成后端逻辑,当后端返回响应码为0时,代表更新数据库成功,那么在前端直接跳转到登录页,进行登录,登录成功后则显示修改后的用户名了
$('#form-name').submit(function (e) {
e.preventDefault();
var name = $("#user-name").val();
var data = {
name:name
};
var jsonData = JSON.stringify(data);
$.ajax({
url:"/api/v1.0/users/name",
type:"post",
data:jsonData,
contentType:"application/json",
dataType:"json",
headers:{
"X-CSRFToken": getCookie("csrf_token")
},
success: function (resp) {
if (resp.errno == "0"){
location.href = "/login.html";
}else {
alert(resp.errmsg)
}
}
})
})
5.测试
说明:测试以18022222222账号为例
- step1 查看数据库中ih_user_profile表,获取所有用户信息
- step2 启动项目
python manage.py runserver
- step3 登录18022222222账号进入我的爱家,点击修改,进入修改页面,如下
- step4 先输入依存在的用户名,点击保存,如果打印用户名已存在,说明逻辑正确
- step5 输入不存在的昵称这里输入的为Hellotaogang,如果成功修改则,,逻辑正确
- step6 查看数据库显示为修改后的昵称,表示前后端逻辑编写正确
七丶在我的爱家上,显示头像用户名以及手机号
说明:这里可以写一个后端接口用来显示出此三项,我这里写了两个接口,第一个是显示头像的,第二个是显示用户名和手机号
1.先看看实现之前的效果
2.显示头像后端逻辑编写
- step1 定义show_avatar视图函数
@api.route("/users/show_avatar", methods=["POST"])
@login_required
def show_avatar():
pass
- step2 因为实现代码太简单,详细过程不细说
# 获取user_id
user_id = g.user_id
# 从数据库中获取avatar_url
try:
user = User.query.filter_by(id=user_id).first()
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="获取图片信息失败")
# 拼接图片完整链接
avatar_url = constants.QINIU_URL_DOMAIN + user.avatar_url
return jsonify(errno=RET.OK, errmsg="OK", data={"avatar_url": avatar_url})
3.显示用户名和手机号后端逻辑编写
- step1 定义show_name_mobile视图函数
@api.route("/users/show_name_mobile", methods=["POST"])
@login_required
def show_name_mobile():
pass
- step2 因为实现代码太简单,详细过程不细说
# 获取用户id
user_id = g.user_id
# 根据用户id 在数据库中获取对应的 用户名和手机号
try:
user = User.query.filter_by(id=user_id).first()
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="获取用户信息失败")
# 获取用户名
use_name = user.name
# 获取用户手机号
user_mobile = user.mobile
# 构造响应数据
data = {
"user_name": use_name,
"user_mobile": user_mobile
}
# 将响应数据返回给前端
return jsonify(errno=RET.OK, errmsg="OK", data=data)
4.显示头像和显示用户名和手机号前端编写(这里只演示显示头像的,后者可以自己尝试编写,基本一样,逻辑简单)
$(document).ready(function(){
$.ajax({
url:"/api/v1.0/users/show_avatar",
type:"post",
headers:{
"X-CSRFToken":getCookie("csrf_token")
},
dataType:"json",
success:function (resp) {
if (resp.errno == "0"){
var avatarUrl = resp.data.avatar_url;
$('#user-avatar').attr("src", avatarUrl)
}else {
alert(resp.errmsg);
}
}
});
5.代码实现后的效果图
八丶最终效果动图
注:这里以18111111111账号为例,进行动图演示