FastAPI中为同一表单实现两个功能按钮的技术问题
问题分析
你遇到的错误核心原因有两个:
- GET请求不支持Form参数:
@app.get("/pdf")接口里用Form(...)获取参数,但GET请求没有请求体,FastAPI会去请求体里找start_date,自然找不到,所以报缺失错误。 - 标签不会携带表单数据:你用
<a>标签跳转/pdf,浏览器只会发起单纯的GET请求,不会把表单里的start_date值自动带到URL里,接口根本接收不到参数。
要解决这个问题,需要从表单提交方式和接口参数获取方式两方面修改:
- 把PDF按钮改成表单提交按钮,指定提交到
/pdf且用GET方法,这样表单数据会自动转成URL查询参数。 - 修改PDF接口,用
Query来获取查询参数,同时设置为可选参数。
代码修改
1. HTML表单修改(替换原标签)
把原来的<a>按钮改成<button>,添加formaction和method属性,让它单独提交到/pdf接口:
<form class="ui form" action="/attendance" method="post"> <!-- 原表单字段保持不变 --> <div class="field"> <table align="center" width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td><label>ID de Trabajador</label></td> <td><input type="number" name="id_worker" placeholder="Ingresar trabajador" style="width:200px"/></td> </tr> <tr> <td><label>Fecha inicial</label></td> <td><input type="date" name="start_date" placeholder="Fecha inicial" style="width:200px"></td> </tr> <tr> <td><label>Fecha final</label></td> <td><input type="date" name="end_date" placeholder="Fecha final" style="width:200px"></td> </tr> <tr> <td><label>Sueldo por día</label></td> <td><input type="number" name="day_wage" placeholder="Sueldo por día" style="width:200px"></td> </tr> </table> </div> <button class="ui blue button" type="submit">Calcular asistencias</button> <!-- 修改后的PDF按钮 --> <button class="ui red button" type="submit" formaction="/pdf" method="get">Generar reporte</button> </form>
formaction属性会覆盖表单默认的action,点击这个按钮时,表单会以GET方法提交到/pdf,同时把所有表单字段(包括start_date)作为查询参数带过去。
2. FastAPI PDF接口修改
把Form换成Query,并设置为可选参数(用Optional和默认值None):
from typing import Optional from datetime import date, datetime @app.get("/pdf") def generate_report(request: Request, start_date: Optional[date] = Query(None)): if start_date: # 若有传入start_date,转成datetime处理(和你的薪资接口逻辑一致) start_date = datetime(start_date.year, start_date.month, start_date.day) print(start_date) # 这里添加生成PDF的逻辑 return {"message": f"Reporte generado para la fecha {start_date.strftime('%d/%m/%y')}"} else: # 未传入start_date时的处理 return {"message": "Por favor ingresa una fecha inicial"}
Query(None)表示这个参数是可选的,用户没填的话也不会报错。- 现在接口会从URL的查询参数里获取
start_date(比如/pdf?start_date=2024-05-01),符合GET请求的参数传递规则。
额外说明
如果不想把其他表单字段(比如id_worker、end_date)带到/pdf的查询参数里,可以用JavaScript来单独获取start_date的值,然后构造URL跳转。比如给按钮加点击事件:
<button class="ui red button" onclick="generatePdf()">Generar reporte</button> <script> function generatePdf() { const startDate = document.querySelector('input[name="start_date"]').value; let url = "/pdf"; if (startDate) { url += `?start_date=${startDate}`; } window.location.href = url; } </script>
这种方式只会带start_date参数,更简洁,适合只需要单个字段的场景。
内容的提问来源于stack exchange,提问作者Ukhu
相关产品推荐
相关产品推荐

