You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在线书店开发遇400 Bad Request: KeyError: 'roomno'问题求助

解决Flask中400 Bad Request: KeyError: 'roomno'的问题

看起来你遇到的核心问题是表单提交时roomno字段没有被正确传递到后端,再加上Flask路由里的逻辑混乱,直接触发了这个KeyError。我帮你梳理下问题点和具体修复方案:

1. 表单提交的两个致命问题

你的HTML代码里有两个直接导致错误的问题:

  • 表单action指向了placeorder,但后端根本没有这个路由,请求找不到对应处理逻辑;
  • 所有地址输入框都加了disabled属性——被disabled的表单元素不会被包含在POST请求的表单数据里,这就导致后端request.form['roomno']完全找不到这个字段,直接抛出KeyError。

修复后的HTML代码片段

<html>
<h1>PLACE ORDER</h1><br>
<!-- 注意变量名从books_data改成book_data,和后端传递的变量对应 -->
<h5><a class="card-title" href="">{{ book_data[0] }}</a></h5>
<h4>{{ book_data[1] }}</h4>
<span>{{ book_data[2] }}</span>
<!-- 用url_for生成正确的路由地址,避免硬编码 -->
<form action="{{ url_for('order_book') }}" method="POST">
<div class="nav-link">
<div class="form-group">
<!-- 区分状态:无地址时显示可编辑输入框,有地址时显示disabled的内容 -->
{% if not addr_data %}
Room no<br><input type="text" name="roomno" required><br><br>
building<br><input type="text" name="building" required><br><br>
street<br><input type="text" name="street" required><br><br>
city<br><input type="text" name="city" required><br><br>
zipcode<br><input type="text" name="zipcode" required><br><br>
{% else %}
Room no<br><input type="text" name="roomno" value={{ addr_data[2] }} disabled><br><br>
building<br><input type="text" name="building" value={{ addr_data[3] }} disabled><br><br>
street<br><input type="text" name="street" value={{ addr_data[4] }} disabled><br><br>
city<br><input type="text" name="city" value={{ addr_data[5] }} disabled><br><br>
zipcode<br><input type="text" name="zipcode" value={{ addr_data[6] }} disabled><br><br>
{% endif %}
Mobilenumber<br><input type="text" name="phoneno" value={{ cust_data[4] }} disabled><br><br>
Email<br><input type="text" name="emailids" value={{ cust_data[3] }} disabled><br><br>
<input type="text" name="book_id" value={{ book_data[1] }} style="display:none">
<input type="text" name="user_id" value={{ cust_data[0] }} style="display:none">
<input type="text" name="book_price" value={{ book_data[8] }} style="display:none">
<input type="submit" class="btn btn-primary" value="Place Order">
</form>
</div>
</div>
</html>

2. Flask路由逻辑重构

你的路由代码里有明显的逻辑嵌套错误,而且变量名也有问题(比如用userid但定义的是user_id),导致流程完全走不通。下面是修复后的完整路由:

@app.route('/order_book',methods=['GET','POST'])
def order_book():    
    if not session.get('logged_in'):        
        return render_template('user_login.html')    
    user_id = session['userid']    
    cur = connection.cursor()    
    cur.execute("SELECT * FROM address WHERE user_id=%s", [user_id])    
    addr_data = cur.fetchone()    

    # 处理POST请求:先判断是提交地址还是提交订单
    if request.method == 'POST':
        # 用户没有地址,先处理地址提交
        if not addr_data:
            try:
                room_no = request.form['roomno']
                building = request.form['building']
                street = request.form['street']
                city = request.form['city']
                zipcode = request.form['zipcode']
                # 注意变量名是user_id,不是userid,避免NameError
                cur.execute("INSERT INTO address(user_id,room_no,building,street,city,zipcode) VALUES(%s,%s,%s,%s,%s,%s)",
                            (user_id, room_no, building, street, city, zipcode))
                connection.commit()
                print('Address Added')
                # 提交后重新获取地址数据,刷新状态
                cur.execute("SELECT * FROM address WHERE user_id=%s", [user_id])
                addr_data = cur.fetchone()
            except KeyError as e:
                # 捕获字段缺失的错误,给用户提示
                return render_template('address.html', error=f"请填写完整地址:缺失字段 {e}")
        else:
            # 用户已有地址,处理订单提交逻辑(这里需要你补充插入订单表的SQL)
            book_id = request.form.get('book_id')
            user_id = request.form.get('user_id')
            book_price = request.form.get('book_price')
            # 示例:插入订单到order表
            # cur.execute("INSERT INTO orders(user_id, book_id, price) VALUES(%s,%s,%s)", (user_id, book_id, book_price))
            # connection.commit()
            print('订单提交成功')
            return redirect(url_for('order_success'))  # 替换成你的订单成功页面

    # GET请求分支:有地址则显示订单页,无地址则显示地址填写页
    if addr_data:
        book_id = request.args.get('book_id1')  # 从GET参数获取book_id
        cur.execute("SELECT * FROM books WHERE book_id=%s", [book_id])
        book_data = cur.fetchone()
        cur.execute("SELECT * FROM login WHERE user_id=%s", [user_id])
        cust_data = cur.fetchone()
        cur.close()
        return render_template('order_book.html', addr_data=addr_data, book_data=book_data, cust_data=cust_data)
    else:
        cur.close()
        return render_template('address.html')  # 确保这个页面是地址填写表单

3. 额外注意事项

  • 建议用request.form.get('field_name')替代直接取键的方式,这样字段缺失时会返回None,而不是直接抛出KeyError,更容易做错误处理;
  • 数据库操作后一定要关闭游标,或者用with语句自动管理连接和游标;
  • 你原来的代码里没有实现订单插入数据库的逻辑,需要补充对应的SQL语句和提交操作。

内容的提问来源于stack exchange,提问作者ChocoSanju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:41:39