前端搜索栏为空触发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
相关产品推荐
相关产品推荐

