1

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.

Chris
  • 18,724
  • 6
  • 46
  • 80
AquaEthan
  • 25
  • 4
  • 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. – MatsLindh Nov 19 '22 at 22:35
  • Does this answer your question? [How to submit HTML form value using FastAPI and Jinja2 Templates?](https://stackoverflow.com/questions/74318682/how-to-submit-html-form-input-value-using-fastapi-and-jinja2-templates) – Chris Nov 20 '22 at 05:33
  • Related answers can be found [here](https://stackoverflow.com/a/73359311/17865804), [here](https://stackoverflow.com/a/71665594/17865804), as well as [here](https://stackoverflow.com/a/70771526/17865804), [here](https://stackoverflow.com/a/74317758/17865804) and [here](https://stackoverflow.com/a/73359311/17865804). – Chris Nov 20 '22 at 05:37
  • Thanks Matslindh! Copied the wrong thing with num. I'ved edited my post. – AquaEthan Nov 20 '22 at 18:06

1 Answers1

0

You need to make sure that the action attribute—which specifies where to send the form-data—is included in the HTML <form> when submitting it (see W3schools <form> tag docs for examples 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 from the drop-down list. 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>
Chris
  • 18,724
  • 6
  • 46
  • 80