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

Python Flask多表单API请求返回400 Bad Request错误排查

问题原因

你遇到的400错误和分支判断结构(if/elif)无关,核心是两个问题:

  • 后端参数取值方式有问题:你直接使用request.args['参数名']的硬编码方式获取URL参数,当请求中没有携带对应参数时,Flask会直接抛出BadRequestKeyError,默认返回400 Bad Request响应。
  • 前端表单设计缺失:你当前的搜索页只有一个name="recipe"的输入框,既没有搜索类型选择控件,也没有食材、营养搜索对应的输入项,提交请求时永远不会携带ingredients、nutrients两个参数。当食谱搜索条件为空时,代码执行到食材/营养参数的判断逻辑,尝试访问不存在的参数键就会直接触发400错误。

你之前单独注释掉其他分支能正常运行,是因为注释后代码不会尝试访问不存在的参数键,自然不会触发报错。

修复方案

1. 调整前端表单结构

增加搜索类型选择器,统一输入入口,确保请求能明确携带搜索类型和关键词,示例代码:

<form class="d-flex justify-content-center" action="/recipes">
  <div class="input-group mb-3" style="max-width: 70%;">
    <!-- 搜索类型下拉选择 -->
    <select class="form-select" name="search_type" style="max-width: 140px;">
      <option value="recipe">按食谱名称搜索</option>
      <option value="ingredients">按食材搜索</option>
      <option value="nutrients">按最低蛋白质含量搜索</option>
    </select>
    <!-- 统一关键词输入框 -->
    <input type="text" class="form-control" placeholder="请输入搜索内容" name="keyword" required>
    <div class="input-group-append">
      <button class="btn btn-primary" type="submit">搜索</button>
    </div>          
  </div>
</form>

如果需要支持多维度营养搜索(比如同时限制脂肪、热量范围),可以在选择营养搜索时通过JS动态展示对应输入框即可。

2. 重构后端路由逻辑

使用request.args.get('参数名', 默认值)的方式安全获取参数,避免参数缺失触发报错;再根据用户选择的搜索类型调用对应API接口,示例代码:

@app.route('/recipes')
def get_recipes():
    # 安全获取参数,参数不存在时默认返回空字符串
    search_type = request.args.get('search_type', 'recipe')
    keyword = request.args.get('keyword', '').strip()

    if not keyword:
        return "搜索关键词不能为空", 400
    
    api_resp = None
    if search_type == 'recipe':
        querystring = {"query": keyword}
        api_resp = requests.request("GET", url + findByRecipe, headers=headers, params=querystring).json()
    elif search_type == 'ingredients':
        # 多食材用逗号分隔即可,符合接口参数要求
        querystring = {"number":"5", "ranking":"1", "ingredients": keyword}
        api_resp = requests.request("GET", url + findByIngredients, headers=headers, params=querystring).json()
    elif search_type == 'nutrients':
        # 校验蛋白质输入为有效数字
        try:
            min_protein = float(keyword)
        except ValueError:
            return "营养搜索请输入有效的蛋白质含量数值(单位:g)", 400
        querystring = {"number":"5", "ranking":"1", "minProtein": min_protein}      
        api_resp = requests.request("GET", url + findByNutrients, headers=headers, params=querystring).json()
    else:
        return "不支持的搜索类型", 400

    return render_template('recipes.html', recipes=api_resp)

优化建议

  • 调用第三方API时建议增加异常捕获(比如超时、接口返回非200状态码的处理),避免第三方服务异常直接导致站点报错
  • 营养搜索如果需要支持多参数过滤,可以在前端增加对应输入项,后端按接口文档组装querystring即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:39:20