本文对应的资料下载地址:https://download.youkuaiyun.com/download/geek_xiong/11548649
目录
个人主页显示用户信息
在主页点击用户名,进入个人主页my.html
界面应该显示用户的头像,用户名以及手机号
url:127.0.0.1:5000/api/v1.0/user
请求方式:GET
后端代码编写
大致流程:
- 获取用户id
- 根据用户id查询数据库
- 将查询的结果返回
代码
# profile.py
@api.route('/user', methods=['GET'])
@login_required
def get_user_profile():
"""个人主页中获取用户信息
包括:用户头像,手机号,用户名
要求:json格式
"""
# 获取用户id
user_id = g.user_id
# 根据用户id查询该用户的信息
try:
user = User.query.get(user_id)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg='获取用户信息失败')
# 判断获取的user是否为空
if user is None:
jsonify(errno=RET.NODATA, errmsg='无效操作')
return jsonify(errno=RET.OK, errmsg='OK', data=user.to_dict())
# models.py
class User(BaseModel, db.Model):
...
def to_dict(self):
"""
将数据转换后字典
:return: 字典
"""
user_dict = {
"user_id": self.id,
"name": self.name,
"mobile": self.mobile,
"avatar": constants.QINIU_URL_DOMAIN + self.avatar_url if self.avatar_url else "",
"create_time": self.create_time.strftime("%Y-%m-%d %H:%M:S")
}
return user_dict
前端代码编写
# my.html
<div class="menu-content">
<img id="user-avatar" src="">
<div class="menu-text">
<h3>用户名:<span id="user-name"></span></h3>
<h5>手机号:<span id="user-mobile"></span></h5>
</div>
</div>
// my.js
$(document).ready(function(){
$.get('/api/v1.0/user', function (resp) {
// 判断用户是否登陆
if (resp.errno == '4101') {
location.href = '/login.html';
} else if (resp.errno == '0') {
// 查新到数据,展示在前台
$('#user-name').html(resp.data.name);
$('#user-mobile').html(resp.data.mobile);
if (resp.data.avatar) {
$('#user-avatar').attr('src', resp.data.avatar);
}
}
}, "json");
});
个人信息修改界面的完善
个人信息的显示
在个人主页点击修改进入该界面,profile.html
如果没有头像和用户名,则不显示,否则显示,如下图所示,
url:127.0.0.1:5000/api/v1.0/user
请求方式:GET
前端代码编写
# profile.html
<li>
<div class="menu-title">
<h3>头像</h3>
</div>
<div class="menu-content">
<img id="user-avatar" src="">
<div class="menu-text">
<form id="form-avatar" enctype="multipart/form-data">
选择头像:<input type="file" accept="image/*" name="avatar">
<input type="submit" class="btn btn-success" value="上传">
</form>
</div>
</div>
</li>
<li>
<div class="menu-title">
<h3>用户名</h3>
</div>
<div class="menu-content">
<form id="form-name">
<input type="text" name="name" id="user-name">
<input type="submit" class="btn btn-success" value="保存">
</form>
<div class="error-msg"><i class="fa fa-exclamation-circle"></i>用户名已存在,请重新设置</div>
</div>
</li>
# profile.js
// 获取用户信息
$.get('/api/v1.0/user', function (resp) {
if (resp.errno == '4104') {
// 未登录,跳转到登陆界面
location.href = '/login.html'
} else if(resp.errno == '0') {
// 有获取到用户信息
$('#user-name').val(resp.data.name);
if (resp.data.avatar) {
$('#user-avatar').attr('src', resp.data.avatar);
}
}
}, "json");
用户名的修改操作
从新输入用户名,点击保存,更新用户名
url:127.0.0.1:5000/api/v1.0/users/name
请求方式:PUT
后端代码编写
大致流程:
- 获取用户id
- 获取提交的用户名
- 判断用户名是否为空
- 保存到数据库中
- 更新session中的name值
- 返回结果
# profile.py
@api.route('/users/name', methods=['PUT'])
@login_required
def change_user_name():
"""修改用户名"""
user_id = g.user_id
req_data = request.get_json()
# 判断参数的完整性
if req_data is None:
return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
# 获取要修改的name值
name = req_data.get('name')
# 判断是否为空
if not name:
return jsonify(errno=RET.PARAMERR, errmsg='用户名不能为空')
# 保存用户名到数据库(更新操作),同时利用数据库的唯一索引判断是否重复
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='设置用户名错误')
# 更新session中的name值
session['name'] = name
# 返回结果
return jsonify(errno=RET.OK, errmsg='修改成功')
前端代码编写
// profile.js
$(document).ready(function () {
...
// 修改用户名
$('#form-name').submit(function (e) {
// 阻止form表单的默认行为
e.preventDefault();
// 获取name值
var name = $('#user-name').val();
// 判断用户名是否为空
if (!name) {
alert('用户名不能为空!');
return
}
// ajax 提交用户名
$.ajax({
url: '/api/v1.0/users/name',
data: JSON.stringify({'name': name}),
type: 'PUT',
contentType: 'application/json',
dataType: 'json',
headers: {
"X-CSRFToken": getCookie('csrf_token')
},
success: function (data) {
if (data.errno == '0') {
$('.error-msg').hide();
showSuccessMsg();
} else if (data.errno == '4001') {
$('.error-msg').show();
} else if (data.errno == '4101') {
location.href = '/login.html';
}
}
});
});
});
实名信息认证
实名信息的显示
如果没有进行过实名认证的话,显示可以输入与按钮
如果已经提交认证信息,则显示实名信息,并不可修改,同时隐藏提交按钮
url:127.0.0.1:5000/api/v1.0/users/auth
请求方式:GET
后端代码编写
大致流程:
- 获取用户id
- 获取用户信息
- 返回结果
# profile.py
@api.route('/users/auth', methods=['GET'])
@login_required
def get_user_auth():
"""获取用户的实名认证信息"""
user_id = g.user_id
try:
user = User.query.get(user_id)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg='获取用户实名信息失败')
if user is None:
return jsonify(errno=RET.NODATA, errmsg='无效操作')
return jsonify(errno=RET.OK, errmsg='OK', data=user.auto_to_dict())
# models.py
class User(...):
...
def auto_to_dict(self):
"""
将实名信息转换成字典
:return: 字典
"""
auto_dict = {
"user_id": self.id,
"real_name": self.real_name,
"id_card": self.id_card
}
return auto_dict
前端代码编写
// auth.js
$(document).ready(function () {
// 查询用户的实名信息
$.get('/api/v1.0/users/auth', function (resp) {
// 判断是否登陆,4101表示未登录
if(resp.errno == '4101'){
location.href = '/login.html'
}else if(resp.errno == '0') {
// 已经登陆,如果返回的real_name与id_card不为null,表示用户有填写实名信息
if (resp.data.real_name && resp.data.id_card){
// 将实名信息填写到页面中,并不再可以修改,同时隐藏按钮
$('#real-name').val(resp.data.real_name);
$('#id-card').val(resp.data.id_card);
$('#real-name').prop('disabled', true);
$('#id-card').prop('disabled', true);
$('#form-auth>input[type=submit]').hide();
}
}
}, "json");
});
实名信息认证
后端代码编写
请求方式:POST
大致流程:
- 获取用户id
- 获取认证信息
- 判断认证信息的完整性
- 保存到数据库中
- 返回结果
# profile.py
@api.route('/users/auth', methods=['POST'])
@login_required
def set_user_auth():
"""保存实名认证信息
包括:真实名、身份证号
要求:json格式
"""
# 获取用户id
user_id = g.user_id
# 获取实名信息
req_data = request.get_json()
if not req_data:
return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
real_name = req_data.get('real_name')
id_card = req_data.get('id_card')
# 判断参数的完整性
if not all([real_name, id_card]):
return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
try:
User.query.filter_by(id=user_id, real_name=None, id_card=None).update({"real_name": real_name, "id_card": id_card})
db.session.commit()
except Exception as e:
current_app.logger.error(e)
db.session.rollback()
return jsonify(errno=RET.DBERR, errmsg='保存实名信息失败')
# 返回结果
return jsonify(errno=RET.OK, errmsg='OK')
前端代码编写
// auth.js
$(document).ready(function () {
// 查询用户的实名信息
...
// 用户实名信息的提交行为
$('#form-auth').submit(function (e) {
// 阻止表单的默认提交行为
e.preventDefault();
// 获取实名信息
var real_name = $('#real-name').val();
var id_card = $('#id-card').val();
// 判断是否为空
if (real_name == "" || id_card == ""){
$('.error-msg').show();
}
// 将数据转换成json格式
var data = {
"real_name": real_name,
"id_card": id_card
};
var json_data = JSON.stringify(data);
// ajax提交,保存实名认证信息
$.ajax({
url: '/api/v1.0/users/auth',
data: json_data,
dataType: 'json',
type: 'post',
contentType: 'application/json',
headers: {
'X-CSRFToken': getCookie('csrf_token')
},
success: function (resp) {
if (resp.errno == '0'){
$('.error-msg').hide();
showSuccessMsg();
$('#real-name').prop('disabled', true);
$('#id-card').prop('disabled', true);
$('#form-auth>input[type=submit]').hide();
}else{
alert(resp.errmsg);
}
}
});
});
});
城区信息
后端代码编写
# api/houses.py
from flask import current_app, jsonify
from . import api
from ihome.models import Area
from ihome.utils.response_code import RET
@api.route('/areas')
def get_area_info():
"""获取区域信息"""
# 查新数据库
try:
area_li = Area.query.all()
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg='数据库异常')
area_dict_li = []
for area in area_li:
area_dict_li.append(area.to_dict())
return jsonify(errno=RET.OK, errmsg='OK', data=area_dict_li)
# ihome/models.py
class Area(BaseModel, db.Model):
"""城区"""
__tablename__ = "ih_area_info"
id = db.Column(db.Integer, primary_key=True) # 区域编号
name = db.Column(db.String(32), nullable=False) # 区域名字
houses = db.relationship("House", backref="area") # 区域的房屋
def to_dict(self):
"""将对象转换成字典"""
area_dict = {
"aid": self.id,
"aname": self.name
}
return area_dict
postman测试
启动项目,打开postman,输入获取城区信息的url,请求方式为get
缓存数据库
由于城区信息会频繁的访问,所以考虑将城区信息取出后保存到redis中,这样再取时先从redis中取,如果redis中没有,在从mysql数据库中取。
大致流程:
- 从redis中获取城区信息
- 有,直接返回
- 没有,继续下一步
- 从mysql数据库中获取城区信息
- 将取出的数据转换成json格式
- 将json数据保存到redis中
- 返回结果
import json
from flask import current_app, jsonify
from . import api
from ihome.models import Area
from ihome.utils.response_code import RET
from ihome import db, redis_store, constants
@api.route('/areas')
def get_area_info():
"""获取区域信息"""
# 从redis中获取数据
try:
resp_json = redis_store.get('area_info')
except Exception as e:
current_app.logger.error(e)
else:
if resp_json is not None:
current_app.logger.info('hide redis area_info')
return resp_json, 200, {"Contant-Type": 'application/json'}
# 查新数据库
try:
area_li = Area.query.all()
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg='数据库异常')
area_dict_li = []
for area in area_li:
area_dict_li.append(area.to_dict())
# 将数据转换为json格式
resp_dict = dict(errno=RET.OK, errmsg='OK', data=area_dict_li)
resp_json = json.dumps(resp_dict)
# 将数据保存到redis中
try:
redis_store.setex('area_info', constants.AREA_INFO_REDIS_CACHE_EXPIRE, resp_json)
except Exception as e:
current_app.logger.error(e)
return resp_json, 200, {"Contant-Type": 'application/json'}
前端代码编写
# newhouse.hmtl
<label for="area-id">所在城区</label>
<select class="form-control" id="area-id" name="area_id">
</select>
<script type="text/html" id="areas-tmpl">
{{ each areas as area }}
<option value="{{ area.aid }}">{{ area.aname }}</option>
{{ /each }}
</script>
<script src="/static/js/template.js"></script>
// newhouse.js
$(document).ready(function(){
$.get('/api/v1.0/areas', function (resp) {
if (resp.errno == '0'){
var areas = resp.data;
// for(var i=0; i<areas.length; i++){
// var area = areas[i];
// // var option = '<option value="'+ area.aid +'">'+ area.aname +'</option>';
// $('#area-id').append('<option value="'+ area.aid +'">'+ area.aname +'</option>');
// }
var _html = template("areas-tmpl", {"areas": areas});
$('#area-id').html(_html);
}else{
alert(resp.errmsg);
}
}, "json");
});