Flask爱家租房--订单(下订单)

本文详细介绍了使用Flask开发租房应用中创建订单的步骤,包括从用户在detail.html点击预定按钮,到booking.html页面的逻辑验证,再到booking.js如何获取house_id和填充页面信息。用户提交订单时,通过ajax向/api/v1.0/orders接口发送请求,后端在orders.py的save_order()函数中处理并保存到数据库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0 、效果展示

detail.html
在这里插入图片描述
booking.html
在这里插入图片描述

1、思路总结

1)用户打开房屋详情页detail.html之后,后端detail.js会判断此访问用户是否为房东,若不是房东,则在详情页的最下方展示“即刻预定”按钮,用户点击后,页面会根据js文件指定的路径,转到/booking.html页面;
在这里插入图片描述

在这里插入图片描述在这里插入图片描述
2)接下来页面/booking.html开始加载,booking.js会对:用户是否已经登录、选定开始结束日期的前后关系、是否完整等进行逻辑判断,同时通过定义函数,截取url中的house_id,通过house_id获得房屋的基本信息,加载到前端页面;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3)用户填写相关信息,点击“提交订单按钮”,向后端路径/api/v1.0/orders发送ajax请求;
在这里插入图片描述
在这里插入图片描述
4)接下来,后端相应接口save_order()进行逻辑处理,
在这里插入图片描述
保存订单信息,提交数据库,并向前端返回order.id。
在这里插入图片描述

2、后端代码

orders.py

@api.route("/orders", methods=["POST"])
@login_required
def save_order():
    """保存订单"""
    user_id = g.user_id

    # 获取参数
    order_data = request.get_json()
    if not order_data:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    house_id = order_data.get("house_id")  # 预订的房屋编号
    start_date_str = order_data.get("start_date")  # 预订的起始时间
    end_date_str = order_data.get("end_date")  # 预订的结束时间

    # 参数检查
    if not all((house_id, start_date_str, end_date_str)):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 日期格式检查
    try:
        # 将请求的时间参数字符串转换为datetime类型
        start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d")
        end_date = datetime.datetime.strptime(end_date_str, "%Y-%m-%d")
        assert start_date <= end_date
        # 计算预订的天数
        days = (end_date - start_date).days + 1  # datetime.timedelta
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="日期格式错误")

    # 查询房屋是否存在
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取房屋信息失败")
    if not house:
        return jsonify(errno=RET.NODATA, errmsg="房屋不存在")

    # 预订的房屋是否是房东自己的
    if user_id == house.user_id:
        return jsonify(errno=RET.ROLEERR, errmsg="不能预订自己的房屋")

    # 2,房屋没有被别人下单
    try:
        # 查询时间冲突的订单数
        count = Order.query.filter(Order.house_id == house_id, Order.begin_date <= end_date,
                                   Order.end_date >= start_date).count()
        #  select count(*) from order where ....
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="检查出错,请稍候重试")
    if count > 0:
        return jsonify(errno=RET.DATAERR, errmsg="房屋已被预订")

    # 订单总额
    amount = days * house.price

    # 保存订单数据
    order = Order(
        house_id=house_id,
        user_id=user_id,
        begin_date=start_date,
        end_date=end_date,
        days=days,
        house_price=house.price,
        amount=amount
    )
    try:
        db.session.add(order)
        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", data={"order_id": order.id})

3、前端js

booking.js

function hrefBack() {
    history.go(-1);
}

function getCookie(name) {
    var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
    return r ? r[1] : undefined;
}

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;
    }, {});
}

function showErrorMsg() {
    $('.popup_con').fadeIn('fast', function() {
        setTimeout(function(){
            $('.popup_con').fadeOut('fast',function(){}); 
        },1000) 
    });
}

$(document).ready(function(){
    // 判断用户是否登录
    $.get("/api/v1.0/session", function(resp) {
        if ("0" != resp.errno) {
            location.href = "/login.html";
        }
    }, "json");
    $(".input-daterange").datepicker({
        format: "yyyy-mm-dd",
        startDate: "today",
        language: "zh-CN",
        autoclose: true
    });
    $(".input-daterange").on("changeDate", function(){
        var startDate = $("#start-date").val();
        var endDate = $("#end-date").val();

        if (startDate && endDate && startDate > endDate) {
            showErrorMsg("日期有误,请重新选择!");
        } else {
            var sd = new Date(startDate);
            var ed = new Date(endDate);
            days = (ed - sd)/(1000*3600*24) + 1;
            var price = $(".house-text>p>span").html();
            var amount = days * parseFloat(price);
            $(".order-amount>span").html(amount.toFixed(2) + "(共"+ days +"晚)");
        }
    });
    var queryData = decodeQuery();
    var houseId = queryData["hid"];

    // 获取房屋的基本信息
    $.get("/api/v1.0/houses/" + houseId, function(resp){
        if (0 == resp.errno) {
            $(".house-info>img").attr("src", resp.data.house.img_urls[0]);
            $(".house-text>h3").html(resp.data.house.title);
            $(".house-text>p>span").html((resp.data.house.price/100.0).toFixed(0));
        }
    });
    // 订单提交
    $(".submit-btn").on("click", function(e) {
        if ($(".order-amount>span").html()) {
            $(this).prop("disabled", true);
            var startDate = $("#start-date").val();
            var endDate = $("#end-date").val();
            var data = {
                "house_id":houseId,
                "start_date":startDate,
                "end_date":endDate
            };
            $.ajax({
                url:"/api/v1.0/orders",
                type:"POST",
                data: JSON.stringify(data),
                contentType: "application/json",
                dataType: "json",
                headers:{
                    "X-CSRFTOKEN":getCookie("csrf_token"),
                },
                success: function (resp) {
                    if ("4101" == resp.errno) {
                        location.href = "/login.html";
                    } else if ("4004" == resp.errno) {
                        showErrorMsg("房间已被抢定,请重新选择日期!");
                    } else if ("0" == resp.errno) {
                        location.href = "/orders.html";
                    }
                }
            });
        }
    });
})

4、前端html

booking.html

<!DOCTYPE html>
<html>
<head> 
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>爱家-预订</title>
    <link href="/static/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <link href="/static/plugins/font-awesome/css/font-awesome.min.css" rel="stylesheet">
    <link href="/static/css/reset.css" rel="stylesheet">
    <link href="/static/plugins/bootstrap-datepicker/css/bootstrap-datepicker.min.css" rel="stylesheet">
    <link href="/static/css/ihome/main.css" rel="stylesheet">
    <link href="/static/css/ihome/booking.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div class="top-bar">
            <div class="nav-bar">
                <h3 class="page-title">预 订</h3>
                <a class="nav-btn fl" href="#" onclick="hrefBack();"><span><i class="fa fa-angle-left fa-2x"></i></span></a>
            </div>
        </div>
        <div class="house-info">
            <img src="/static/images/home01.jpg">
            <div class="house-text">
                <h3>房屋标题</h3>
                <p><span>300</span>/</p>
            </div>
        </div>
        <div class="select-date">
            <div class="select-date-header">入住时间</div>
            <div class="input-daterange input-group">
                <input type="text" class="input-sm form-control" id="start-date" />
                <span class="input-group-addon"></span>
                <input type="text" class="input-sm form-control" id="end-date" />
            </div>
        </div>
        <div class="submit-order">
            <span class="order-amount">订单总额:¥<span></span></span>
            <span class="submit-btn">提交订单</span>
        </div>
    </div>
    <div class="popup_con">
        <div class="popup">
            <p>日期有误,请重新选择!</p>
        </div>
        <div class="mask"></div>
    </div>
    
    <script src="/static/js/jquery.min.js"></script>
    <script src="/static/plugins/bootstrap/js/bootstrap.min.js"></script>
    <script src="/static/plugins/bootstrap-datepicker/js/bootstrap-datepicker.min.js"></script>
    <script src="/static/plugins/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js"></script>
    <script src="/static/js/ihome/booking.js"></script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值