Flask项目之手机端租房网站的实战开发(八)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41782425/article/details/86302733

说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

接着上一篇博客继续往下写 :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.图片存储服务---七牛云

  • 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插件来发送表单数据

<form id="form-avatar" enctype="multipart/form-data">
    选择头像:<input type="file" accept="image/*" name="avatar">
    <input type="submit" class="btn btn-success" value="上传">
</form>

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"

<form id="form-name">

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账号为例,进行动图演示

猜你喜欢

转载自blog.csdn.net/qq_41782425/article/details/86302733