Python FastAPI:来自 Jinja2 模板的不同数量的输入项

Python FastAPI: varying number of input items from a Jinja2 template

我正在尝试使用 Jinja2FastAPI 为我的 API 构建一个简单的网络界面 (UI)。包含两个输入的 UI 的一部分是固定的,但另一部分是动态创建的,通过用字典中的 keys/items 填充 HTML 模板。为简单起见,我使用的字典只有 3 个 keys/items,但实际上可能有 8 个或 11 个键和项。 我正在努力收集动态生成的输入,因为我不确定如何在不必在代码中硬编码它们的名称的情况下执行此操作。下面是函数中硬编码参数的外观示例。有什么方法可以一次收集所有输入,然后以某种方式“解压”它们吗?我考虑过将输入放入 editable table,但后来我再次努力收集 table 的内容。

这是UI:

这里是 Python 代码:

from fastapi import FastAPI, Request, Form
from fastapi.templating import Jinja2Templates

dct = {"ctp_a": 1,
       "ctp_b": 2,
       "ctp_c": 20}

app = FastAPI()
templates = Jinja2Templates(directory="templates/")

@app.get("/form")
def form_post(request: Request):
    result = dct
    return templates.TemplateResponse('form3.html', context={'request': request, 'result': result})

@app.post("/form")
def form_post(
        request: Request, multiply_by: int = Form(...),
        # this is hardcoded which I don't like
        ctp_a_nm: str = Form(...), ctp_b_nm: str = Form(...), ctp_c_nm: str = Form(...),
        # this is hardcoded as well
        ctp_a: int = Form(...), ctp_b: int = Form(...), ctp_c: int = Form(...)
        ):
    
    result = {ctp_a_nm: ctp_a*multiply_by,
              ctp_b_nm: ctp_b*multiply_by,
              ctp_c_nm: ctp_c*multiply_by}
    
    return templates.TemplateResponse('form3.html', context={'request': request, 'result': result})

这是 html 模板。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Sample Form</title>
    </head>
    <body>
        <form method="post">
            
            <label for="multiply_by">Multiply by</label><br>
            <input type="number" name="multiply_by" value="2"/><br><br>

            {% for key in result %}
                <input type="text" name="{{ key }}_nm" value="{{ key }}" readonly />
                <input type="number" name="{{ key }}" value="{{ result[key] }}"/><br>
            {% endfor %}
            
            <br><input type="submit">
            
        </form>
    </body>
</html>

此答案基于@MatsLindh 在评论中提出的建议。

POST 请求部分可以这样重写,允许 n 个 keys/values。

@app.post("/form")
def form_post(
        request: Request,
        multiply_by: int = Form(...),
        name: List[str] = Form(...),
        key: List[int] = Form(...),
        ):
    
    result = dict(zip(name, [k*multiply_by for k in key]))

    return templates.TemplateResponse('form3.html', context={'request': request, 'result': result})

需要更改 UI 以便引用具有唯一名称的名称和值。

    {% for key in result %}
        <input type="text" name="name" value="{{ key }}" readonly />
        <input type="number" name="key" value="{{ result[key] }}"/><br>
    {% endfor %}