From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Tue, 2 Dec 2025 04:49:32 +0000 (+0100) Subject: 🐛 Fix parsing extra `Form` parameter list (#14303) X-Git-Tag: 0.123.2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cf40df24d1d199fd25d034fc87fcae284fc23a2;p=thirdparty%2Ffastapi%2Ffastapi.git 🐛 Fix parsing extra `Form` parameter list (#14303) Co-authored-by: Sebastián Ramírez --- diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 0f25a3c360..2b2e6c5af9 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -903,9 +903,13 @@ async def _extract_form_body( if value is not None: values[field.alias] = value field_aliases = {field.alias for field in body_fields} - for key, value in received_body.items(): + for key in received_body.keys(): if key not in field_aliases: - values[key] = value + param_values = received_body.getlist(key) + if len(param_values) == 1: + values[key] = param_values[0] + else: + values[key] = param_values return values diff --git a/tests/test_forms_single_model.py b/tests/test_forms_single_model.py index 880ab38200..1db63f0214 100644 --- a/tests/test_forms_single_model.py +++ b/tests/test_forms_single_model.py @@ -2,6 +2,7 @@ from typing import List, Optional from dirty_equals import IsDict from fastapi import FastAPI, Form +from fastapi._compat import PYDANTIC_V2 from fastapi.testclient import TestClient from pydantic import BaseModel, Field from typing_extensions import Annotated @@ -17,11 +18,27 @@ class FormModel(BaseModel): alias_with: str = Field(alias="with", default="nothing") +class FormModelExtraAllow(BaseModel): + param: str + + if PYDANTIC_V2: + model_config = {"extra": "allow"} + else: + + class Config: + extra = "allow" + + @app.post("/form/") def post_form(user: Annotated[FormModel, Form()]): return user +@app.post("/form-extra-allow/") +def post_form_extra_allow(params: Annotated[FormModelExtraAllow, Form()]): + return params + + client = TestClient(app) @@ -131,3 +148,33 @@ def test_no_data(): ] } ) + + +def test_extra_param_single(): + response = client.post( + "/form-extra-allow/", + data={ + "param": "123", + "extra_param": "456", + }, + ) + assert response.status_code == 200, response.text + assert response.json() == { + "param": "123", + "extra_param": "456", + } + + +def test_extra_param_list(): + response = client.post( + "/form-extra-allow/", + data={ + "param": "123", + "extra_params": ["456", "789"], + }, + ) + assert response.status_code == 200, response.text + assert response.json() == { + "param": "123", + "extra_params": ["456", "789"], + }