Passing dropdown selection from HTML form to FastAPI endpoint

I’m trying to capture the selected option from an HTML dropdown and send it to my FastAPI backend. When I submit the form, I get an error saying a field is missing. Can someone help me figure out what’s wrong?

Here’s my FastAPI code:

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

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

@api.get('/')
def home():
    return 'welcome'

@api.get("/dropdown")
def show_form(request: Request):
    message = "Pick a color"
    return templates.TemplateResponse('dropdown.html', context={'request': request, 'message': message})

@api.post("/dropdown")
def handle_form(request: Request, message = Form(...)):
    return templates.TemplateResponse('dropdown.html', context={'request': request, 'message': message})

And here’s my HTML template:

<!DOCTYPE html>
<html>
<head>
    <title>Color Picker</title>
</head>
<body>
<form method="post">
    <select name="colors" id="colors">
        <option value="red">Red</option>
        <option value="blue">Blue</option>
        <option value="green">Green</option>
        <option value="yellow">Yellow</option>
    </select>
    <button type="submit">Choose</button>
</form>

<p>Selected: {{ message }}</p>

</body>
</html>

I keep getting this error when I try to submit:

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

I want to select a color from the dropdown, click the button, and see the chosen color displayed on the page.

wait, are you handlling the GET request right? when the page loads, message might be undefined. try adding a default value in your GET route or check if that’s the problem. also - does the form accually submit or fail before hitting your endpoint?

Your form field name doesn’t match your FastAPI parameter. The HTML dropdown uses name="colors" but your endpoint expects message. FastAPI needs these names to match exactly. Change your endpoint from message = Form(...) to colors = Form(...), then update your template response: return templates.TemplateResponse('dropdown.html', context={'request': request, 'message': colors}). That’ll fix it - FastAPI will grab the dropdown value and pass it to your template.

you’ve got a mismatch in your form field names. the dropdown uses name="colors" but your fastapi code is looking for message. fix it by either changing your html to name="message" or updating the endpoint to accept colors = Form(...).