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

前端搜索栏为空触发422错误,如何捕获并处理?

问题描述

我用HTMX结合FastAPI实现了带输入框的搜索栏,从静态用户字典列表中搜索用户信息,输入时能实时更新结果,但清空搜索栏后旧结果不会消失,后台还会抛出POST /search HTTP/1.1" 422 Unprocessable Entity错误,直到输入匹配内容才恢复。需要解决这个问题,要么捕获错误返回正确的HTML响应,要么让搜索逻辑支持空字符串。


方案1:支持空字符串搜索(推荐)

直接修改搜索逻辑,处理空搜索词的场景,避免抛出422异常,让HTMX能正常接收响应并更新页面。

修改后的FastAPI代码:

@app.post('/search', response_class=HTMLResponse)
async def search(request: Request, hx_request: Optional[str] = Header(None), search: str = Form(default="")):
    # 修正字符串处理:不可变类型需重新赋值,同时去除前后空格
    search_term = search.strip().lower()
    print(f'search term is: {search_term}')
    
    # 空搜索词时返回所有用户(若不需要显示全部,可改为search_results = [])
    if not search_term:
        search_results = data_users
    else:
        search_results = list(filter(
            lambda user: search_term in user['name'].lower() or search_term in user['email'].lower(),
            data_users
        ))
    
    # 生成结果HTML:无匹配时显示跨列提示,避免布局错乱
    if not search_results:
        search_result_html = '<tr><td colspan="2" class="text-center py-4">无匹配结果</td></tr>'
    else:
        search_result_html = "".join(
            f"""
            <tr>
                <td><div class="my-4 p-2">{user['name']}</div></td>
                <td><div class="my-4 p-2">{user['email']}</div></td>
            </tr>
            """
            for user in search_results
        )
    
    context = {'request': request, 'result': search_result_html}
    if hx_request:
        return HTMLResponse(content=search_result_html, status_code=200)
    else:
        return temp.TemplateResponse('search.html', context)

关键修改点:

  • 给Form参数设置default="",确保空输入能被正确接收
  • 修复search.lower()无效问题:字符串是不可变类型,需赋值给新变量search_term
  • 空搜索词时直接返回所有用户(或空列表,按需调整)
  • 无结果时生成跨两列的提示行,避免表格布局异常

方案2:捕获空输入并返回正确响应(保留原有异常逻辑)

如果需要保留空输入抛异常的逻辑,需确保异常处理返回的HTML能正确更新HTMX目标,同时修复代码缺陷:

修改后的FastAPI代码:

from fastapi import HTTPException, status

@app.post('/search', response_class=HTMLResponse)
async def search(request: Request, hx_request: Optional[str] = Header(None), search: str = Form(default="")):
    search_term = search.strip().lower()
    print(f'search term is: {search_term}')
    
    try:
        if not search_term:
            raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="无搜索关键词")

        search_results = list(filter(
            lambda user: search_term in user['name'].lower() or search_term in user['email'].lower(),
            data_users
        ))
        
        if not search_results:
            raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="无匹配结果")
        
        search_result_html = "".join(
            f"""
            <tr>
                <td><div class="my-4 p-2">{user['name']}</div></td>
                <td><div class="my-4 p-2">{user['email']}</div></td>
            </tr>
            """
            for user in search_results
        )
        context = {'request': request, 'result': search_result_html}
        if hx_request:
            return HTMLResponse(content=search_result_html, status_code=200)
        else:
            return temp.TemplateResponse('search.html', context)
    except HTTPException as e:
        # 生成跨列提示HTML,修复布局问题
        error_html = '<tr><td colspan="2" class="text-center py-4">{}</td></tr>'.format(e.detail)
        # 返回200状态码,确保HTMX能正常处理响应(默认忽略4xx/5xx响应)
        return HTMLResponse(content=error_html, status_code=200)

前端优化(可选)

若选择方案2,可给输入框添加hx-swap-error="true",确保错误响应也能更新结果区域:

<input
        class="border border-gray-600 bg-gray-800 p-2 rounded-lg w-full mb-5"
        type="search"
        name="search"
        placeholder="开始输入搜索用户..."
        hx-post="/search"
        hx-trigger="input changed delay:500ms, search"
        hx-target="#search-results"
        hx-indicator="#loading"
        hx-swap-error="true"
        />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 22:27:42