说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!
接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/86512594
目录
一丶用户房屋管理后端编写
二丶用户房屋管理前端编写
三丶测试用户管理后端接口
四丶主页幻灯片房屋信息后端编写
五丶主页幻灯片房屋信息前端编写
六丶测试主页幻灯片接口和区县信息以及房屋信息缓存
七丶房屋详情页后端编写
八丶房屋详情页前端编写
九丶测试房屋详情页面显示正确数据是否成功
一丶用户房屋管理后端编写
1.需求分析:在我的房源界面显示出房东发布的房源信息,在前端中就需要从后端接口中发送获取用户id,房屋标题,图片以及房屋信息,显示在前端页面中
2.逻辑编写
- step1 在houses.py中定义接口
@api.route("/user/houses", methods=["GET"])
@login_required
def get_user_houses():
"""
获取房东发布的房源信息
:return:
"""
pass
- step2 获取用户id
user_id = g.user_id
- step3 通过用户id从数据库USER中获取用户对象,通过user对象来获取用户发布的房屋
try:
user = User.query.get(user_id)
houses = user.houses
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="获取数据失败")
- step4 在models.py中house里面定义一个to_basic_dict方法,将房屋基本信息转换成字典数据
def to_basic_dict(self):
"""将基本信息转换为字典数据"""
house_dict = {
"house_id": self.id,
"title": self.title,
"price": self.price,
"area_name": self.area.name,
"img_url": constants.QINIU_URL_DOMAIN + self.index_image_url if self.index_image_url else "",
"room_count": self.room_count,
"order_count": self.order_count,
"address": self.address,
"user_avatar": constants.QINIU_URL_DOMAIN + self.user.avatar_url if self.user.avatar_url else "",
"ctime": self.create_time.strftime("%Y-%m-%d")
}
return house_dict
- step5 将查询到的房屋信息转换成字典数据,添加到定义的houses_list列表中
houses_list = []
for house in houses:
houses_list.append(house.to_basic_dict())
- step6 最后返回正确响应数据
return jsonify(errno=RET.OK, errmsg="OK", data={"houses":houses_list})
二丶用户房屋管理前端编写
1.在myhouse.js中通过get请求方式向后端接口发送请求,通过后端返回的正确响应以及data数据,传到前端html中的template模本进行数据显示,如下编写
$.get("/api/v1.0/user/houses", function(resp){
if ("0" == resp.errno) {
$("#houses-list").html(template("houses-list-tmpl", {houses:resp.data.houses}));
} else {
$("#houses-list").html(template("houses-list-tmpl", {houses:[]}));
}
});
2.引入template.js模板,在my.html中进行如下编写
三丶测试用户管理后端接口
1.之前在编写发布房源接口时,已经发布过房源信息了,所以当进入我的房源页面时,就会向后端接口发送请求,获取房源数据,显示在页面上,如下图所示
2.查看数据库房屋信息表ih_house_info
四丶主页幻灯片房屋信息后端编写
1.分析:首先主页幻灯片上显示的房屋信息,需要在后端定义一个接口,在这个接口中我们需要在数据库中将房屋订单数目最多的5条数据查询出来,展示到主页上,这个需求也是刚开始开发项目的需求,因为主页时用户大量访问的,所以这5条数据需要缓存到redis数据库中,减少我们对数据库的查询
2.逻辑编写(具体实现)
- step1 定义视图函数,此接口因为是在主页所以不需要用户登录验证
@api.route("/houses/index", methods=["GET"])
def get_house_index():
"""
获取主页幻灯片房屋信息
:return:
"""
pass
- step2 查询数据库获取房屋订单数目最多的5条数据
try:
# 查询房屋订单倒序排序并显示5条
houses = House.query.order_by(House.order_count.desc()).limit(constants.HOME_PAGE_MAX_HOUSES)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="查询数据失败")
- step3 判断数据是否存在,不存在则返回异常错误信息
if not houses:
return jsonify(errno=RET.NODATA, errmsg="无相关数据")
- step4 将查询到的房屋信息转换成字典数据,添加到定义的houses_list列表中,如过房屋未设置主图片,则跳过
houses_list = []
for house in houses:
if not house.index_image_url:
continue
houses_list.append(house.to_basic_dict())
- step5 将列表数据转换从json格式的数据,并存到redis数据库中
try:
json_houses = json.dumps(houses_list)
redis_store.setex("home_page_data", constants.HOME_PAGE_DATA_REDIS_EXPIRES, json_houses)
except Exception as e:
current_app.logger.error(e)
- step6 返回正确响应数据
return '{"errno":"0", "errmsg":"OK", "data":%s}' % json_houses, 200, {"Content-Type":"application/json"}
- step7 因为第一次是不存在缓存数据的,所以我们在进入函数时,就先从redis中拿取数据
try:
ret = redis_store.get("home_page_data")
except Exception as e:
current_app.logger.error(e)
ret = None
- step8 此时需要对获取数据进行判断,当获取数据结果不为空时,则返回给前端正确响应数据,不存在时else就在数据库中进行数据查询,再将查询结果写入到redis数据库
# 当ret获取数据结果不为空时,则返回给前端正确响应数据,不存在时else就在数据库中进行数据查询,再将查询结果写入到redis数据库
if ret:
current_app.logger.info("house index info from redis")
# 因为redis中保存的是json字符串,所以直接进行字符串拼接返回
return '{"errno":0, "errmsg":"OK", "data":%s}' % ret, 200, {"Content-Type": "application/json"}
else:
# 查询数据库获取房屋订单数目最多的5条数据
try:
# 查询房屋订单倒序排序并显示5条
houses = House.query.order_by(House.order_count.desc()).limit(constants.HOME_PAGE_MAX_HOUSES)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="查询数据失败")
五丶主页幻灯片房屋信息前端编写
1.在主页前端index.js中,需要向后端接口发送请求来获取主页幻灯片要展示的房屋信息
// 获取幻灯片要展示的房屋基本信息
$.get("/api/v1.0/houses/index", function(resp){
if ("0" == resp.errno) {
$(".swiper-wrapper").html(template("swiper-houses-tmpl", {houses:resp.data}));
// 设置幻灯片对象,开启幻灯片滚动
var mySwiper = new Swiper ('.swiper-container', {
loop: true,
autoplay: 2000,
autoplayDisableOnInteraction: false,
pagination: '.swiper-pagination',
paginationClickable: true
});
}
});
2.在主页页面中选择区县按钮块,需要从后端接口获取区县信息
// 获取区县信息
$.get("/api/v1.0/areas", function(resp){
if ("0" == resp.errno) {
$(".area-list").html(template("area-list-tmpl", {areas:resp.data}));
$(".area-list a").click(function(e){
$("#area-btn").html($(this).html());
$(".search-btn").attr("area-id", $(this).attr("area-id"));
$(".search-btn").attr("area-name", $(this).html());
$("#area-modal").modal("hide");
});
}
});
3.在主页index.html中进行一个模板使用,将后端返回的响应数据显示在模板中,幻灯片部分如下
4.在主页index.html中区县模板,编写如下
六丶测试主页幻灯片接口和区县信息以及房屋信息缓存
1.幻灯片接口
2.区县信息显示
3.查看项目运行日志
4.此时查看数据库缓存
七丶房屋详情页后端编写
1.分析:①在房屋详情页面,角色分为房东以及客户,当客户进入时对于前端页面来说需显示预定功能按钮,如是房东角色进入就不展示此功能按钮;②对于角色来说,那么就需要用到user_id了;③尝试从session中去获取用户id,如果存在,说明用户为登录状态,那么将用户id返回给前端,不存在返回user_id = -1
2.逻辑编写
- step1 创建视图函数,需要前端给后端传递房屋id
@api.route("/houses/", methods=["GET"])
def get_house_detail(house_id):
"""
获取房屋详情
:param house_id:
:return:
"""
pass
- step2 从session中尝试获取用户id,没有则赋值-1
user_id = session.get("user_id", "-1")
- step3 校验house_id, 不存在则返回错误信息提示
if not house_id:
return jsonify(errno=RET.PARAMERR, errmsg="参数缺失")
- step4 通过house_id 查询数据库获取房屋对象
try:
house = House.query.get(house_id)
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="查询数据失败")
- step5 判断对象是否存在
if not house:
return jsonify(errno=RET.NODATA, errmsg="房屋不存在")
- step6 在models.py文件House类中定义to_full_dict方法,用作于将详细信息转换为字典数据;在这个方法里面需要将房屋图片,房屋设施以及评论信息,单独添加到列表中,最后在将该列表以值的方式保存到字典house_dict中
def to_full_dict(self):
"""将详细信息转换为字典数据"""
house_dict = {
"hid": self.id,
"user_id": self.user_id,
"user_name": self.user.name,
"user_avatar": constants.QINIU_URL_DOMAIN + self.user.avatar_url if self.user.avatar_url else "",
"title": self.title,
"price": self.price,
"address": self.address,
"room_count": self.room_count,
"acreage": self.acreage,
"unit": self.unit,
"capacity": self.capacity,
"beds": self.beds,
"deposit": self.deposit,
"min_days": self.min_days,
"max_days": self.max_days,
}
# 房屋图片
img_urls = []
for image in self.images:
img_urls.append(constants.QINIU_URL_DOMAIN + image.url)
house_dict["img_urls"] = img_urls
# 房屋设施
facilities = []
for facility in self.facilities:
facilities.append(facility.id)
house_dict["facilities"] = facilities
# 评论信息
comments = []
orders = Order.query.filter(Order.house_id == self.id, Order.status == "COMPLETE", Order.comment != None) \
.order_by(Order.update_time.desc()).limit(constants.HOUSE_DETAIL_COMMENT_DISPLAY_COUNTS)
for order in orders:
comment = {
"comment": order.comment, # 评论的内容
"user_name": order.user.name if order.user.name != order.user.mobile else "匿名用户", # 发表评论的用户
"ctime": order.update_time.strftime("%Y-%m-%d %H:%M:%S") # 评价的时间
}
comments.append(comment)
house_dict["comments"] = comments
return house_dict
- step7 将查询到的房屋对象转换成字典
try:
house_data = house.to_full_dict()
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DATAERR, errmsg="数据错误")
- step8 将房屋详情数据转换成json格式的数据,并存到redis数据库中
json_houses = json.dumps(house_data)
try:
redis_store.setex("house_info_%s" % house_id, constants.HOUSE_DETAIL_REDIS_EXPIRE_SECOND, json_houses)
except Exception as e:
current_app.logger.error(e)
- step9 构造响应数据, 并返回
resp = '{"errno":"0", "errmsg":"OK", "data":{"user_id":%s, "house":%s}}' %(user_id, json_houses), 200, {"Content-Type": "application/json"}
return resp
- step10 尝试从redis数据库中获取房屋详情信息, 出现异常则使ret为None,所以需要在进入函数后,那么需要从去数据库中获取房屋详情信息
try:
ret = redis_store.get("house_info_%s" % house_id)
except Exception as e:
current_app.logger.error(e)
ret = None
- step11 对ret进行判断, 存在不为None 则直接返回正确响应数据即可
if ret:
current_app.logger.info("house info from redis")
return '{"errno":"0", "errmsg":"OK", "data":{"user_id":%s, "house":%s}}' % (user_id, ret), 200, {"Content-Type": "application/json"}
八丶房屋详情页前端编写
1.在detail.js文件中
- step1 定义decodeQuery函数,用作于解析提取url中的查询字符串参数
function decodeQuery(){
var search = decodeURI(document.location.search);
return search.replace(/(^\?)/, '').split('&').reduce(function(result, item){
values = item.split('=');
result[values[0]] = values[1];
return result;
}, {});
}
- step2 在$(document).ready(function(){}回调函数中,获取详情页面要展示的房屋编号
var queryData = decodeQuery();
var houseId = queryData["id"];
- step3 获取房屋详细信息
$.get("/api/v1.0/houses/" + houseId, function(resp){
if ("0" == resp.errno) {
$(".swiper-container").html(template("house-image-tmpl", {img_urls:resp.data.house.img_urls, price:resp.data.house.price}));
$(".detail-con").html(template("house-detail-tmpl", {house:resp.data.house}));
// resp.user_id为访问页面用户,resp.data.user_id为房东
if (resp.data.user_id != resp.data.house.user_id) {
$(".book-house").attr("href", "/booking.html?hid="+resp.data.house.hid);
$(".book-house").show();
}
var mySwiper = new Swiper ('.swiper-container', {
loop: true,
autoplay: 2000,
autoplayDisableOnInteraction: false,
pagination: '.swiper-pagination',
paginationType: 'fraction'
});
}
})
2.在detail.html文件中
- step1 房屋详情页面中幻灯片房屋信息编写如下
- step2 房屋标题,房屋地址,房屋详情,配套设施以及评价信息编写如下
九丶测试房屋详情页面显示正确数据是否成功
1.运行项目,在浏览器输入http://127.0.0.1:5000,即进入网站主页,如下图所示
2.点击主页任意幻灯片,进入房屋详情页面
3.前端房屋完整信息图如下
4.查询数据库中房屋信息表以及设备设施表id和house_id为3的数据与前端页面显示数据进行对比
- step1 在ih_house_info 房屋信息表中查看id=3的数据
- step2 在ih_house_facility 房屋设备表中,查看house_id为3的设备数据为9条,与前端页面house_id为3的设备信息一致
- step3 将step2 查询结果与ih_facility_info设备表进行一一对应,然后与第3点前端房屋完整信息图进行对比验证
5.查看redis数据库中缓存的房屋详情数据
6.查看项目运行日志,显示成功说明本次进入房屋详情页使用的页面数据为缓存数据