flask项目1实战:4、个人中心(待完善)

在这里插入图片描述

(根据居然老师直播课内容整理)

一、登录装饰器

  • 有很多页面进入前需要判断用户是否登录,甚至会使用到用户信息
  • flask框架有一个钩子函数 和 before_request,每次请求前都会调用
  • 本项目不是所有页面都需要登录,不注册登录也可浏览部分页面
  • 还可以用装饰器,

1、定义装饰器函数

  • 该函数不属于业务逻辑函数,并且很多方法是共用的,建议定义在 utils包内commons.py 中
  • 定义闭包,@functools()
  • 在内层函数实现登录检查
    • 从session中取出user_id
    • 判断user_id是否为空
      • 为空,返回 错误信息:用户未登录
      • 存在,表示已登录,用g对象存储user_id ,返回被装饰函数
# lghome/commons.py

# view_func 被装饰的函数
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'
    # 上传后保存的文件名
    # key = 'my-python-logo.png'
    # 生成上传 Token,可以指定过期时间等
    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('上传图片失败')
    # print(ret)
    # print("-"*50)
    # print(info)

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')
    # print(image_file)
    # print(type(image_file))

    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='上传图片失败')

    # 保存到数据库中
    # file_name FoRZHZTBj2xRSDa_Se0Rvx26qm0C
    # URL  http://qkgi1wsiz.hd-bkt.clouddn.com/FoRZHZTBj2xRSDa_Se0Rvx26qm0C
    # 保存 file_name
    # http://qkgi1wsiz.hd-bkt.clouddn.com/
    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数据
    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="用户信息查询失败")

    # print("user.auth_to_dict()=",user.auth_to_dict())
    return jsonify(errno=RET.OK,errmsg="ok",data=user.auth_to_dict())

猜你喜欢

转载自blog.csdn.net/laoluobo76/article/details/110632101
今日推荐