(根据居然老师直播课内容整理)
一、登录装饰器
- 有很多页面进入前需要判断用户是否登录,甚至会使用到用户信息
- flask框架有一个钩子函数 和 before_request,每次请求前都会调用
- 本项目不是所有页面都需要登录,不注册登录也可浏览部分页面
- 还可以用装饰器,
1、定义装饰器函数
- 该函数不属于业务逻辑函数,并且很多方法是共用的,建议定义在 utils包内commons.py 中
- 定义闭包,@functools()
- 在内层函数实现登录检查
- 从session中取出user_id
- 判断user_id是否为空
- 为空,返回 错误信息:用户未登录
- 存在,表示已登录,用g对象存储user_id ,返回被装饰函数
def login_requre(view_func):
@functools.wrapper(view_func)
def wrapper(*args,**kwargs):
user_id = session.get('user_id')
if user_id is not None:
g.user_id=user_id
return view_func(*args, **kwargs)
else:
return jsonify(errno=RET.SESSIONERR, errmsg='用户未登陆')
return wrapper
二、用户上传头像(修改用户信息)
1、七牛云图片上传功能封装
def storage(file_data):
q = Auth(access_key, secret_key)
bucket_name = 'home-image-flask'
token = q.upload_token(bucket_name, None, 3600)
ret, info = put_data(token, None, file_data)
if info.status_code == 200:
return ret.get('key')
else:
raise Exception('上传图片失败')
2、用户上传头像接口设计
2.1 请求方式
选项 |
方案 |
请求方法 |
POST |
请求地址 |
/users/avatar |
2.2请求参数:表单参数
参数名 |
类型 |
是否必传 |
说明 |
avatar |
file |
是 |
用户头像 |
2.3 响应结果
响应结果 |
响应内容 |
保存失败 |
响应错误提示 |
保存成功 |
返回当前页面 |
3、用户上传头像接口定义
- 首先应用登录装饰器
- 如果没有登录,直接返回 sessionerr,跳转到登录界面
- 进入函数后,首先获取g对象中的user_id
- 获取参数image_file
- 如果参数为None(即未传图片),返回报错
- 读取文件
- 保存图片
- 保存图片有以下几种方法
- 数据库服务器:对服务器性质、资源、数据软件要求高
- 服务器目录:防止文件重名等,资源、性能要求等,
- 第三方平台:如七牛云平台(个人系统推荐)
- 自己搭建文件存储服务器:如FastDFS 快速分布式文件存储系统,主要用于电商企业,以图片为主;HDFS Hadoop分布式文件系统(什么文件都行)
- 保存图片路径
- 将图片地址保存到数据库中,仅保存文件名即可,图片地址的前半部分域名保存常量文件中
lghome/api_1_0/profile.py
@api.route("/users/avatar",methods=["POST"])
@login_required
def set_user_avatar(): """
设置用户的头像
:param: 图片
:return: avatar_url 头像的地址
"""
user_id = g.user_id
image_file = request.files.get('avatar')
if image_file is None:
return jsonify(errno=RET.PARAMERR, errmsg='未上传图片')
image_data = image_file.read()
try:
file_name = storage(image_data)
except Exception as e:
logging.error(e)
return jsonify(errno=RET.THIRDERR, errmsg='上传图片失败')
try:
User.query.filter_by(id=user_id).update({
"avatar_url": file_name})
db.session.commit()
except Exception as e:
db.session.rollback()
logging.error(e)
return jsonify(errno=RET.DBERR, errmsg='保存图片信息失败')
avatar_url = constants.QINIU_URL_DOMAIN + file_name
return jsonify(errno=RET.OK, errmsg='保存成功', data={
"avatar_url": avatar_url})
3、
三、修改用户名
1、修改用户名接口设计
1.1 请求方式
选项 |
方案 |
请求方法 |
PUT |
请求地址 |
/users/name |
1.2请求参数:表单参数
参数名 |
类型 |
是否必传 |
说明 |
name |
string |
是 |
用户名 |
1.3 响应结果
响应结果 |
响应内容 |
保存失败 |
响应错误提示 |
保存成功 |
|
2、修改用户名接口定义
- 首先应用登录装饰器
- 如果没有登录,直接返回 sessionerr,跳转到登录界面
- 进入函数后,首先获取g对象中的user_id
- 获取参数name
- 如果参数为None,返回错误信息
- 更新用户名称
- 如果用户重复会报数据异常,name是uniqure
- 返回结果
@api.route("users/name",methods=["PUT"])
@login_required
def change_user_name():
"""
修改用户名
:return: 修改用户名成功或者失败
"""
user_id = g.user_id
request_data = request.get_json()
if request_data is None:
return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
user_name=request_data.get("name")
try:
User.query.filter_by(id=user_id).update({
"name": user_name})
db.session.commit()
except IntegrityError as e :
logging.error(e)
db.session.rollback()
return jsonify(errno=RET.DBERR, errmsg='用户名已经存在')
except Exception as e:
logging.error(e)
db.session.rollback()
return jsonify(errno=RET.DBERR, errmsg='设置用户名错误')
session["name"] = user_name
return jsonify(errno=RET.OK, errmsg='OK')
四、获取个人信息(刷新用户信息页)
1、修改用户名接口设计
1.1 请求方式
选项 |
方案 |
请求方法 |
GET |
请求地址 |
/user |
1.2请求参数:无
1.3 响应结果
名字 |
类型 |
是否必须 |
说明 |
errno |
字符串 |
否 |
错误代码 |
errmsg |
字符串 |
否 |
错误内容 |
data |
字典 |
否 |
个人信息字典 |
2、修改用户名接口定义
- 首先应用登录装饰器
- 如果没有登录,直接返回 sessionerr,跳转到登录界面
- 进入函数后,首先获取g对象中的user_id
- 根据user_id获取用户信息
- 如果用户信息不存或数据报错,返回错误信息
根据个人信息字典(在User类中定义返回个人信息的字典方法)
@api.route("/user",methods=["GET"])
@login_required
def get_user_profile():
"""
获取个人信息
:return: 用户名,用户头像URL
"""
user_id = g.user_id
print(user_id)
try:
user=User.query.get(user_id)
print(user)
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR,errmsg="用户信息查询失败")
if user is None:
print("None")
return jsonify(errno=RET.NODATA, errmsg="用户信息查询失败")
print("user.to_dict()=",user.to_dict())
return jsonify(errno=RET.OK,errmsg="",data=user.to_dict())
六、实名认证
- 需要与公安系统对接,按接口文档开发即可,个人无法完成数据校验。
- 本项目暂不判断实名认证信息,直接保存到数据库
1、实名认证接口设计
1.1 请求方式
选项 |
方案 |
请求方法 |
POST |
请求地址 |
/users/auth |
1.2请求参数:表单参数
参数名 |
类型 |
是否必传 |
说明 |
id_card |
string |
是 |
身份证号 |
real_name |
string |
是 |
真实姓名 |
1.3 响应结果
名字 |
类型 |
是否必须 |
说明 |
errno |
字符串 |
否 |
错误代码 |
errmsg |
字符串 |
否 |
错误内容 |
data |
字典 |
否 |
{“id_card”:“xxx”,“real_name”:“XXXXX”} |
2、实名认证接口定义
- 首先应用登录装饰器
- 如果没有登录,直接返回 sessionerr,跳转到登录界面
- 进入函数后,首先获取g对象中的user_id
- 获取参数,判断有效性
- 调用与公安接口(此功能暂无),默认验证成功
- 根据user_id更新用户真实姓名和身份证
- 返回结果
@api.route("/users/auth",methods=["POST"])
@login_required
def set_user_auth():
"""
保存实名认证信息
:return:
"""
user_id = g.user_id
request_dict = request.get_json()
real_name=request_dict.get("real_name")
id_card=request_dict.get("id_card")
if not all([real_name,id_card]):
return jsonify(errno=RET.DATAERR,errmsg="参数不完整")
try:
User.query.filter_by(id=user_id).update({
"real_name":real_name,"id_card":id_card})
db.session.commit()
except Exception as e:
logging(e)
db.session.rollback()
return jsonify(errno=RET.DBERR,errmsg="保存数据失败")
return jsonify(errno=RET.OK,errmsg="ok",data={
"real_name":real_name,"id_card":id_card})
3、优化实名认证接口定义
- 如果用户实名认证后,不应该再次进行实名认证,并且不能修改
- 进入函数后,直接判断用户是否实名注册过,如果注册过,就报错返回
- 通过user_id获取user信息
- 通all[user.real_name,user_id_card]判断是实名注册过
try:
user=User.query.get(user_id)
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR,errmsg="用户信息查询失败")
if all([user.real_name,user.id_card]):
return jsonify(errno=RET.DATAEXIST,errmsg="用户已实名认证过,不能再修改")
七、获取实名认证信息
- 需要与公安系统对接,按接口文档开发即可,个人无法完成数据校验。
- 本项目暂不判断实名认证信息,直接保存到数据库
1、获取实名认证信息接口设计
1.1 请求方式
选项 |
方案 |
请求方法 |
POST |
请求地址 |
/users/auth |
1.2请求参数:无
1.3 响应结果
名字 |
类型 |
是否必须 |
说明 |
errno |
字符串 |
否 |
错误代码 |
errmsg |
字符串 |
否 |
错误内容 |
data |
字典 |
否 |
{“id_card”:“xxx”,“real_name”:“XXXXX”} |
2、获取实名认证接口定义
- 首先应用登录装饰器
- 如果没有登录,直接返回 sessionerr,跳转到登录界面
- 进入函数后,首先获取g对象中的user_id
- 根据user_id更新用户真实姓名和身份证
- 返回结果
@api.route("/users/auth",methods=["GET"])
@login_required
def get_user_auth():
"""
获取个人信息
:return: 用户名,用户头像URL
"""
user_id = g.user_id
try:
user=User.query.get(user_id)
print(user)
except Exception as e:
logging.error(e)
return jsonify(errno=RET.DBERR,errmsg="用户信息查询失败")
if user is None:
print("None")
return jsonify(errno=RET.DBERR, errmsg="用户信息查询失败")
return jsonify(errno=RET.OK,errmsg="ok",data=user.auth_to_dict())