menu

Questions & Answers

How to submit selected value from HTML dropdown list to FastAPI backend?

How do I submit the value selected from an HTML dropdown list using FastAPI in the backend and HTML/Jinja2 template in the frontend?

Here is my code for the app so far:

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


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


@app.get('/')
def read_form():
    return 'hello world'


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


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

Here is the HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Sample Form</title>
</head>
<body>
<form method="post">

    <select name="names" id="names">
        <option value="n1">Name 1</option>
        <option value="n2">Name 2</option>
        <option value="n3">Name 3</option>
        <option value="n5">Name 4</option>
    </select>
    <input type="submit" value="Submit">
</form>
    
<p>Result: {{ result }}</p>

</body>
</html>

Here is the error message:

{"detail":[{"loc":["body","result"],"msg":"field required","type":"value_error.missing"}]}

The goal is to select a name, then click submit, and finally, have it displayed below.

Comments:
2023-01-22 00:10:12
The signature of the controller function should match your select name: def form_post(request: Request, names: str = Form(...)): - you can then include this as "result": names to your template. Where num is from I have no idea about, since you haven't referenced that parameter in your included code.
2023-01-22 00:10:12
2023-01-22 00:10:12
Related answers can be found here, here, as well as here, here and here.
2023-01-22 00:10:12
Thanks Matslindh! Copied the wrong thing with num. I'ved edited my post.
Answers(1) :

You need to make sure to include the action attribute in the form, which specifies where to send the form-data when a form is submitted (see W3schools <form> tag docs as well). Also, in the <select> element that is used to create the drop-down list, make sure to use the same name used to define the Form parameter in your endpoint. As per W3schools <select> tag docs:

The name attribute is needed to reference the form data after the form is submitted (if you omit the name attribute, no data from the drop-down list will be submitted).

Each <option> element inside the <select> should have a value attribute containing the data value to submit to the server when that option is selected. If no value attribute is included, the value defaults to the text contained inside the element. You can include a selected attribute on an <option> element to make it selected by default when the page first loads.

Working Example

app.py

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

app = FastAPI()
templates = Jinja2Templates(directory='templates')

@app.post('/submit')
def submit(car: str = Form(...)):
    return car

@app.get('/', response_class=HTMLResponse)
def main(request: Request):
    return templates.TemplateResponse('index.html', {'request': request})

templates/index.html

<!DOCTYPE html>
<html>
   <body>
      <form method="POST" action="/submit">
         <label for="cars">Choose a car:</label>
         <select name="car" id="cars">
            <option value="volvo">Volvo</option>
            <option value="saab">Saab</option>
            <option value="opel">Opel</option>
            <option value="audi">Audi</option>
         </select>
         <br><br>
         <input type="submit" value="Submit">
      </form>
   </body>
</html>