Flask综合案例展示二手车信息页、详情页和用户浏览记录、收藏信息

  • Post author:
  • Post category:其他




展示信息页

在这里插入图片描述


先写思路:

  • 根据图我们可以得到需要返回的数据
  • 在models的车类中添加方法返回我们需要的数据
  • 然后根据前端查询车的品牌、模型等各种信息不同展示数据,这里只简单写了品牌和模型

models.py文件添加方法:

class Car(db.Model):
	...
    def to_list_dict(self):
        # 返回列表页的数据
        # 需要的数据:品牌,模型 detail
        # 价格,年份,公里数  id  默认图片
        car_obj_dict = {
            'brand': self.brande.name,
            'model': self.model.name,
            'detail': self.model.detail,
            'price': self.price,
            'car_register_time': self.annual_datetime,
            'car_distance': self.car_distance,
            'car_id': self.id,
            # 默认图片
            'index_image_url': QINIUURL+self.index_image_url
        }
        return car_obj_dict

然后是展示数据的函数:

@api.route('/cars')
def cars_list_info():
    # 将是一个get请求,返回车辆列表
    # 有可能为空
    brand = request.args.get('brand')
    car_model = request.args.get('model')
    print(request.args.get('price'))

    if len(brand) == 0 and len(car_model) == 0:
        cars_lists = Car.query.all()
        print(cars_lists)
        ret_data_list = []
        for each in cars_lists:
            # 调用对象的方法来实现转dict
            ret = each.to_list_dict()
            print(ret)
            # 添加进字典
            ret_data_list.append(ret)
        print(ret_data_list)
        return jsonify(data=ret_data_list)

    elif len(brand) == 0 and len(car_model) !=0:
        # 只有型号没有品牌
        car_lists = Car.query.all()
        ret_data_list = []  # todo 需要返回的数据
        for each in car_lists:
            if each.brande.car_model == car_model:
                print(car_model)

        return jsonify(data=ret_data_list)

    elif len(brand) != 0 and len(car_model) ==0:
        # 只有品牌
        brand_id = Brande.query.filter_by(name=brand).first().id
        cars_lists = Car.query.filter_by(brande_id=brand_id).all()
        ret_data_list = []  # todo 需要返回的数据
        for each in cars_lists:
            # 调用对象的方法来实现转dict
            ret = each.to_list_dict()
            print(ret)
            # 添加进字典
            ret_data_list.append(ret)
        return jsonify(data=ret_data_list)

    return jsonify(msg='ok')



展示车辆详情页

  • 还是写个方法返回需要的数据,因为需要的数据太多,这里不多写
  • 然后写一个接口返回数据,而且详情页需要添加当前的车辆id到redis中,以便后来查询用户的浏览记录
@api.route('/car_detail')
def cat_detail():
    # 这个是详情页,只需要获取car_id
    car_id = request.args.get('car_id')
    car_obj = Car.query.get(car_id)
    # 检验数据是否为空
    if not car_obj:
        return jsonify(errcode=constant.RET_CAR_NOTFOUND, errmsg='car_id出错')
    # todo 当用户登录的情况下,存储car_id到redis数据库8中,类型用列表,有个g变量存了user_id
    user_id = session.get('user_id')
    if user_id:
        try:
            history_key = 'history_%s' % user_id
            # 可能插入重复,所以要删除原来的再加入
            redis_store.lrem(history_key, 0, car_id)
            # 进行存储,左插入,获取使用lrange
            redis_store.lpush(history_key, car_id)
        except Exception as e:
            print(e)
            return jsonify(errcode=constant.RET_REDIS_INSERT_ERR, errmsg='redis插入错误')

    print(request.args)
    print(car_obj)  # todo 获取到了这辆车,然后展示六个表内容和图片,to_detail_dict()
    # todo 防止频繁访问mysql,存进redis
    redis_key = 'mysql-redis_%s' % car_id  # 存进redis的key名
    redis_data = redis_store.get(redis_key)
    if redis_data:
        # 注意bytes转码
        ret_dict = redis_data.decode()
    else:
        # 字典存进redis要序列化
        try:
            ret_dict = json.dumps(car_obj.to_detail_dict())
            redis_store.set(redis_key, ret_dict, constant.CAR_INFO_REDIS_EXPIRES)
        except Exception as e:
            print(e)
            return jsonify(errcode=constant.RET_REDIS_INSERT_ERR, errmsg='redis插入错误')
    # 返回信息,和data
    ret_dict = json.loads(ret_dict)
    return jsonify(msg='ok', data=ret_dict)



添加和展示收藏信息(MySql存储)

在这里插入图片描述


先写思路:

  • 首先要验证是否登录,然后session获取user_id
  • 在用户登录的前提下,添加收藏信息函数为:collect_cars(),添加数据到多对多关系表中
  • 然后是展示收藏数据函数为:show_collect(),直接查询返回即可

相关代码,这里面重点是

多对多关系表的建立和操作

@api.route('/collect')
@login_required
def collect_cars():
    # todo 收藏车,根据get发送的carid
    car_id = request.args.get('car_id')
    car_obj = Car.query.get(car_id)
    # 分别获取car和user对象,收藏是车对用户,1对多
    user_id = session.get('user_id')
    user_obj = User.query.get(user_id)

    # 判断非空
    if not all([car_obj, user_obj]):
        return jsonify(msg='用户不存在', code=constant.USER_NOT_LOGIN)
    try:
        print('car_obj.users')
        # 这是收藏车
        car_obj.users.append(user_obj)
        db.session.commit()
    except Exception as e:
        print(e)
        db.session.rollback()
        return jsonify(msg='db数据库出错', code=constant.DB_COMMIT_ERR)

    return jsonify(msg='ok', code=constant.RET_OK)


@api.route('/show_collect')
@login_required
def show_collect():
    # 收藏数据,是多对多关系
    user_id = session.get('user_id')
    user_obj = User.query.get(user_id)
    user_phone = user_obj.phone
    # 判断非空
    if not user_obj:
        return jsonify(msg='用户不存在', code=constant.USER_NOT_LOGIN)

    # print(user_obj.cars)
    # 如果收藏为空则返回msg=null
    if not len(user_obj.cars):
        return jsonify(msg='null', code=constant.RET_CAR_NOTFOUND)
    # 返回的数据列表
    ret_list = []
    for car_obj in user_obj.cars:
        ret_list.append(car_obj.to_list_dict())
    return jsonify(code=constant.RET_OK, data=ret_list, user_phone=user_phone)



flask-sqlalchemy 数据多对多关系

如何创建多对多关系,在models文件添加中间表模型,SqlAlchemy会自动帮你处理多对多关系

# 这个是系统会帮你创建的中间表
registrations = db.Table("registrations", 
# 字段名sc_user_id关联的是用户id
db.Column("sc_user_id", db.Integer, db.ForeignKey("sc_users.id")),
						# 字段名sc_car_id关联车的id
                         db.Column("sc_car_id", db.Integer, db.ForeignKey("sc_cars_info.id"))
                         )

class User(db.Model):
    __tablename__ = 'sc_users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), unique=True, nullable=True)
    password = db.Column(db.String(100), nullable=True)
    phone = db.Column(db.String(11), nullable=False)
    # # 与car表建立联系,backref表示可以通过car.user_set查询,secondary指定副表名称
    cars = db.relationship("Car",
                           secondary=registrations,
                           backref=db.backref("user_set", lazy="dynamic"))
                          
class Car(db.Model):
    __tablename__ = 'sc_cars_info'
    id = db.Column(db.Integer, primary_key=True)
    # 关联user
    users = db.relationship('User', secondary=registrations,
                            backref=db.backref('cars_set'), lazy='dynamic')

创建之后记得迁移



怎么添加两者关系到中间表

  • 截取一段代码,car_obj和user_obj分别是查询得到的Car和User对象
  • 利用append()添加对象就是添加两者的关系,例子为用户收藏了某车辆,收藏关系是人对车是多对多
    try:
        print('car_obj.users')
        # 这是收藏车
        car_obj.users.append(user_obj)
        db.session.commit()
    except Exception as e:
        print(e)
        db.session.rollback()
        return jsonify(msg='db数据库出错', code=constant.DB_COMMIT_ERR)



查询关系

  • 直接查询User对象的cars属性即可,是一个列表存储着car对象
# 收藏数据,是多对多关系
    user_id = session.get('user_id')  # 查询到登录信息,并得到user对象
    user_obj = User.query.get(user_id)

    ret_list = []  # 返回的数据列表
    for car_obj in user_obj.cars:  
    	# 遍历user对象的cars属性即可
        ret_list.append(car_obj.to_list_dict())
    return jsonify(code=constant.RET_OK, data=ret_list, user_phone=user_phone)



浏览记录(redis存储)

在这里插入图片描述


先写思路:

  • 首先要验证是否登录,然后session获取user_id
  • 在用户登录的前提下,当用户访问详情页(详情页接口函数写)的时候存储car_id到redis数据库中,类型用列表
  • 然后写一个接口返回用户浏览记录数据

返回用户浏览数据代码:

@api.route('/userhistory')
@login_required
def user_history():
    # 用户的浏览记录,放在redis中存储,打开车辆详情页就存储,用户登录才保存
    user_id = session.get('user_id')
    user_obj = User.query.get(user_id)

    # 判断非空
    if not user_obj:
        return jsonify(msg='用户不存在', code=constant.USER_NOT_LOGIN)
    history_key = 'history_%s' % user_id

    # 判断redis是否存在数据
    redis_data = redis_store.lrange(history_key, 0, -1)
    if redis_data:
        ret_list = []
        try:
            for car_id in redis_data:
                # 取出来是Bytes类型
                car_id = car_id.decode()
                print(car_id)
                car_obj = Car.query.get(car_id)
                ret_list.append(car_obj.to_list_dict())
            return jsonify(code=constant.RET_OK, data=ret_list)
        except Exception as e:
            return jsonify(msg='redis数据库出错', code=constant.RET_REDIS_OUTPUT_ERR)
    return jsonify(msg='null', code=constant.RET_CAR_NOTFOUND)



前端js展示数据逻辑:

  • 向后端发送请求浏览数据信息,获得一个字典里两个key值,当msg的值不为ok时则展示内容为空,否则去遍历data值,然后展示所有内容
/**
 * Created by phoebobo on 2019/7/12.
 */

$(function () {

    var get_url = 'http://127.0.0.1:5000/api/v1.0/userhistory';
    $.ajax({
        url: get_url,
        type: 'GET',

        xhrFields: {
            withCredentials: true
        },
        success: function (ret) {
            console.log(ret);
            if (ret['code'] != 0){
                console.log('errrrrr');
                $('.car_cate_item').append("<p id='p1'>暂无收藏车辆</p><a href='https://www.guazi.com/hz/buy/'><p id='p2'>去逛逛瓜子海量车源")
            }
            else {
                var data = ret['data'];
                var str = "<li class='car_detail'>";
                $.each(data, function (index, dict) {
                    console.log(index, dict);
                     str +="<a href='carDetail.html?car_id="+dict.car_id+"' class='to_car_detail'>" +
                         "<img src='"+dict.index_image_url+"' width='180px' height='120px'/>" +
                         "<p class='cate_car_title'>"
                    +dict.brand+' '+dict.model+' '+dict.detail+ "</p><p class='cate_intro_car'>"
                    +'¥'+dict.price+'万 '+dict.car_register_time+' ' +dict.car_distance+'万里程'+"</p></a>";

                });
                str += "</li>";
                $('.car_cate_item').html(str);
            }
        },
        error: function (data) {
            console.log(data)
        }
    })
});



版权声明:本文为paul0926原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。