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

FastAPI中为同一表单实现两个功能按钮的技术问题

问题分析

你遇到的错误核心原因有两个:

  1. GET请求不支持Form参数:@app.get("/pdf")接口里用Form(...)获取参数,但GET请求没有请求体,FastAPI会去请求体里找start_date,自然找不到,所以报缺失错误。
  2. 标签不会携带表单数据:你用<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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 23:05:03