mirror of https://github.com/tiangolo/fastapi.git
🐛 Fix body validation error response, remove variable name when it is not embedded (#1553)
This commit is contained in:
parent
31df2ea940
commit
12bc9285f7
|
|
@ -215,7 +215,6 @@ You will receive a response telling you that the data is invalid containing the
|
||||||
{
|
{
|
||||||
"loc": [
|
"loc": [
|
||||||
"body",
|
"body",
|
||||||
"item",
|
|
||||||
"size"
|
"size"
|
||||||
],
|
],
|
||||||
"msg": "value is not a valid integer",
|
"msg": "value is not a valid integer",
|
||||||
|
|
|
||||||
|
|
@ -642,9 +642,17 @@ async def request_body_to_args(
|
||||||
field = required_params[0]
|
field = required_params[0]
|
||||||
field_info = get_field_info(field)
|
field_info = get_field_info(field)
|
||||||
embed = getattr(field_info, "embed", None)
|
embed = getattr(field_info, "embed", None)
|
||||||
if len(required_params) == 1 and not embed:
|
field_alias_omitted = len(required_params) == 1 and not embed
|
||||||
|
if field_alias_omitted:
|
||||||
received_body = {field.alias: received_body}
|
received_body = {field.alias: received_body}
|
||||||
|
|
||||||
for field in required_params:
|
for field in required_params:
|
||||||
|
loc: Tuple[str, ...]
|
||||||
|
if field_alias_omitted:
|
||||||
|
loc = ("body",)
|
||||||
|
else:
|
||||||
|
loc = ("body", field.alias)
|
||||||
|
|
||||||
value: Any = None
|
value: Any = None
|
||||||
if received_body is not None:
|
if received_body is not None:
|
||||||
if (
|
if (
|
||||||
|
|
@ -655,7 +663,7 @@ async def request_body_to_args(
|
||||||
try:
|
try:
|
||||||
value = received_body.get(field.alias)
|
value = received_body.get(field.alias)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
errors.append(get_missing_field_error(field.alias))
|
errors.append(get_missing_field_error(loc))
|
||||||
continue
|
continue
|
||||||
if (
|
if (
|
||||||
value is None
|
value is None
|
||||||
|
|
@ -667,7 +675,7 @@ async def request_body_to_args(
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
if field.required:
|
if field.required:
|
||||||
errors.append(get_missing_field_error(field.alias))
|
errors.append(get_missing_field_error(loc))
|
||||||
else:
|
else:
|
||||||
values[field.name] = deepcopy(field.default)
|
values[field.name] = deepcopy(field.default)
|
||||||
continue
|
continue
|
||||||
|
|
@ -686,7 +694,9 @@ async def request_body_to_args(
|
||||||
awaitables = [sub_value.read() for sub_value in value]
|
awaitables = [sub_value.read() for sub_value in value]
|
||||||
contents = await asyncio.gather(*awaitables)
|
contents = await asyncio.gather(*awaitables)
|
||||||
value = sequence_shape_to_type[field.shape](contents)
|
value = sequence_shape_to_type[field.shape](contents)
|
||||||
v_, errors_ = field.validate(value, values, loc=("body", field.alias))
|
|
||||||
|
v_, errors_ = field.validate(value, values, loc=loc)
|
||||||
|
|
||||||
if isinstance(errors_, ErrorWrapper):
|
if isinstance(errors_, ErrorWrapper):
|
||||||
errors.append(errors_)
|
errors.append(errors_)
|
||||||
elif isinstance(errors_, list):
|
elif isinstance(errors_, list):
|
||||||
|
|
@ -696,12 +706,12 @@ async def request_body_to_args(
|
||||||
return values, errors
|
return values, errors
|
||||||
|
|
||||||
|
|
||||||
def get_missing_field_error(field_alias: str) -> ErrorWrapper:
|
def get_missing_field_error(loc: Tuple[str, ...]) -> ErrorWrapper:
|
||||||
if PYDANTIC_1:
|
if PYDANTIC_1:
|
||||||
missing_field_error = ErrorWrapper(MissingError(), loc=("body", field_alias))
|
missing_field_error = ErrorWrapper(MissingError(), loc=loc)
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
missing_field_error = ErrorWrapper( # type: ignore
|
missing_field_error = ErrorWrapper( # type: ignore
|
||||||
MissingError(), loc=("body", field_alias), config=BaseConfig,
|
MissingError(), loc=loc, config=BaseConfig,
|
||||||
)
|
)
|
||||||
return missing_field_error
|
return missing_field_error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ single_error = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"ctx": {"limit_value": 0.0},
|
"ctx": {"limit_value": 0.0},
|
||||||
"loc": ["body", "item", 0, "age"],
|
"loc": ["body", 0, "age"],
|
||||||
"msg": "ensure this value is greater than 0",
|
"msg": "ensure this value is greater than 0",
|
||||||
"type": "value_error.number.not_gt",
|
"type": "value_error.number.not_gt",
|
||||||
}
|
}
|
||||||
|
|
@ -114,22 +114,22 @@ single_error = {
|
||||||
multiple_errors = {
|
multiple_errors = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", 0, "name"],
|
"loc": ["body", 0, "name"],
|
||||||
"msg": "field required",
|
"msg": "field required",
|
||||||
"type": "value_error.missing",
|
"type": "value_error.missing",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", 0, "age"],
|
"loc": ["body", 0, "age"],
|
||||||
"msg": "value is not a valid decimal",
|
"msg": "value is not a valid decimal",
|
||||||
"type": "type_error.decimal",
|
"type": "type_error.decimal",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", 1, "name"],
|
"loc": ["body", 1, "name"],
|
||||||
"msg": "field required",
|
"msg": "field required",
|
||||||
"type": "value_error.missing",
|
"type": "value_error.missing",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", 1, "age"],
|
"loc": ["body", 1, "age"],
|
||||||
"msg": "value is not a valid decimal",
|
"msg": "value is not a valid decimal",
|
||||||
"type": "type_error.decimal",
|
"type": "type_error.decimal",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ def test_openapi_schema():
|
||||||
price_missing = {
|
price_missing = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", "price"],
|
"loc": ["body", "price"],
|
||||||
"msg": "field required",
|
"msg": "field required",
|
||||||
"type": "value_error.missing",
|
"type": "value_error.missing",
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ price_missing = {
|
||||||
price_not_float = {
|
price_not_float = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", "price"],
|
"loc": ["body", "price"],
|
||||||
"msg": "value is not a valid float",
|
"msg": "value is not a valid float",
|
||||||
"type": "type_error.float",
|
"type": "type_error.float",
|
||||||
}
|
}
|
||||||
|
|
@ -114,12 +114,12 @@ price_not_float = {
|
||||||
name_price_missing = {
|
name_price_missing = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", "name"],
|
"loc": ["body", "name"],
|
||||||
"msg": "field required",
|
"msg": "field required",
|
||||||
"type": "value_error.missing",
|
"type": "value_error.missing",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", "price"],
|
"loc": ["body", "price"],
|
||||||
"msg": "field required",
|
"msg": "field required",
|
||||||
"type": "value_error.missing",
|
"type": "value_error.missing",
|
||||||
},
|
},
|
||||||
|
|
@ -128,11 +128,7 @@ name_price_missing = {
|
||||||
|
|
||||||
body_missing = {
|
body_missing = {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{"loc": ["body"], "msg": "field required", "type": "value_error.missing",}
|
||||||
"loc": ["body", "item"],
|
|
||||||
"msg": "field required",
|
|
||||||
"type": "value_error.missing",
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ def test_post_invalid_body():
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": ["body", "weights", "__key__"],
|
"loc": ["body", "__key__"],
|
||||||
"msg": "value is not a valid integer",
|
"msg": "value is not a valid integer",
|
||||||
"type": "type_error.integer",
|
"type": "type_error.integer",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ def test_exception_handler_body_access():
|
||||||
"body": '{"numbers": [1, 2, 3]}',
|
"body": '{"numbers": [1, 2, 3]}',
|
||||||
"errors": [
|
"errors": [
|
||||||
{
|
{
|
||||||
"loc": ["body", "numbers"],
|
"loc": ["body"],
|
||||||
"msg": "value is not a valid list",
|
"msg": "value is not a valid list",
|
||||||
"type": "type_error.list",
|
"type": "type_error.list",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ def test_post_validation_error():
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"detail": [
|
"detail": [
|
||||||
{
|
{
|
||||||
"loc": ["body", "item", "size"],
|
"loc": ["body", "size"],
|
||||||
"msg": "value is not a valid integer",
|
"msg": "value is not a valid integer",
|
||||||
"type": "type_error.integer",
|
"type": "type_error.integer",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue