This commit is contained in:
Sebastian Lim 2026-03-16 10:21:04 +00:00 committed by GitHub
commit dd04e1ce13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 2 deletions

View File

@ -751,7 +751,11 @@ def _is_json_field(field: ModelField) -> bool:
def _get_multidict_value(
field: ModelField, values: Mapping[str, Any], alias: str | None = None
field: ModelField,
values: Mapping[str, Any],
alias: str | None = None,
*,
default_on_missing: bool = True,
) -> Any:
alias = alias or get_validation_alias(field)
if (
@ -776,8 +780,9 @@ def _get_multidict_value(
):
if field.field_info.is_required():
return
else:
if default_on_missing:
return deepcopy(field.default)
return None
return value
@ -961,6 +966,7 @@ async def request_body_to_args(
body_to_process = received_body
fields_to_extract: list[ModelField] = body_fields
provided_form_fields: set[str] | None = None
if (
single_not_embedded_field
@ -968,6 +974,17 @@ async def request_body_to_args(
and isinstance(received_body, FormData)
):
fields_to_extract = get_cached_model_fields(first_field.field_info.annotation)
provided_form_fields = {
field.name
for field in fields_to_extract
if _get_multidict_value(
field,
received_body,
alias=get_validation_alias(field),
default_on_missing=False,
)
is not None
}
if isinstance(received_body, FormData):
body_to_process = await _extract_form_body(fields_to_extract, received_body)
@ -977,6 +994,12 @@ async def request_body_to_args(
v_, errors_ = _validate_value_with_model_field(
field=first_field, value=body_to_process, values=values, loc=loc
)
if (
provided_form_fields is not None
and not errors_
and isinstance(v_, BaseModel)
):
v_.__pydantic_fields_set__ = provided_form_fields
return {first_field.name: v_}, errors_
for field in body_fields:
loc = ("body", get_validation_alias(field))

View File

@ -31,6 +31,20 @@ def post_form_extra_allow(params: Annotated[FormModelExtraAllow, Form()]):
return params
class FormModelFieldsSet(BaseModel):
field_1: bool = True
@app.post("/form-model-fields-set/")
def post_form_model_fields_set(model: Annotated[FormModelFieldsSet, Form()]):
return {"fields_set": sorted(model.model_fields_set)}
@app.post("/body-model-fields-set/")
def post_body_model_fields_set(model: FormModelFieldsSet):
return {"fields_set": sorted(model.model_fields_set)}
client = TestClient(app)
@ -139,3 +153,14 @@ def test_extra_param_list():
"param": "123",
"extra_params": ["456", "789"],
}
def test_default_field_not_marked_as_set_for_form_model():
body_response = client.post("/body-model-fields-set/", json={})
form_response = client.post("/form-model-fields-set/", data={})
assert body_response.status_code == 200, body_response.text
assert form_response.status_code == 200, form_response.text
assert body_response.json() == {"fields_set": []}
assert form_response.json() == {"fields_set": []}