mirror of https://github.com/tiangolo/fastapi.git
🐛 Fix OpenAPI schema support for computed fields when using `separate_input_output_schemas=False` (#13207)
Co-authored-by: Sofie Van Landeghem <svlandeg@users.noreply.github.com> Co-authored-by: svlandeg <svlandeg@github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: svlandeg <sofie.vanlandeghem@gmail.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
5126e099bd
commit
f95a174288
|
|
@ -180,8 +180,13 @@ def get_schema_from_model_field(
|
||||||
],
|
],
|
||||||
separate_input_output_schemas: bool = True,
|
separate_input_output_schemas: bool = True,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
|
computed_fields = field._type_adapter.core_schema.get("schema", {}).get(
|
||||||
|
"computed_fields", []
|
||||||
|
)
|
||||||
override_mode: Union[Literal["validation"], None] = (
|
override_mode: Union[Literal["validation"], None] = (
|
||||||
None if separate_input_output_schemas else "validation"
|
None
|
||||||
|
if (separate_input_output_schemas or len(computed_fields) > 0)
|
||||||
|
else "validation"
|
||||||
)
|
)
|
||||||
# This expects that GenerateJsonSchema was already used to generate the definitions
|
# This expects that GenerateJsonSchema was already used to generate the definitions
|
||||||
json_schema = field_mapping[(field, override_mode or field.mode)]
|
json_schema = field_mapping[(field, override_mode or field.mode)]
|
||||||
|
|
@ -203,9 +208,14 @@ def get_definitions(
|
||||||
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
|
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
|
||||||
Dict[str, Dict[str, Any]],
|
Dict[str, Dict[str, Any]],
|
||||||
]:
|
]:
|
||||||
|
has_computed_fields: bool = any(
|
||||||
|
field._type_adapter.core_schema.get("schema", {}).get("computed_fields", [])
|
||||||
|
for field in fields
|
||||||
|
)
|
||||||
|
|
||||||
schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)
|
schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)
|
||||||
override_mode: Union[Literal["validation"], None] = (
|
override_mode: Union[Literal["validation"], None] = (
|
||||||
None if separate_input_output_schemas else "validation"
|
None if (separate_input_output_schemas or has_computed_fields) else "validation"
|
||||||
)
|
)
|
||||||
validation_fields = [field for field in fields if field.mode == "validation"]
|
validation_fields = [field for field in fields if field.mode == "validation"]
|
||||||
serialization_fields = [field for field in fields if field.mode == "serialization"]
|
serialization_fields = [field for field in fields if field.mode == "serialization"]
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@ from .utils import needs_pydanticv2
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="client")
|
@pytest.fixture(name="client")
|
||||||
def get_client():
|
def get_client(request):
|
||||||
app = FastAPI()
|
separate_input_output_schemas = request.param
|
||||||
|
app = FastAPI(separate_input_output_schemas=separate_input_output_schemas)
|
||||||
|
|
||||||
from pydantic import BaseModel, computed_field
|
from pydantic import BaseModel, computed_field
|
||||||
|
|
||||||
|
|
@ -32,6 +33,7 @@ def get_client():
|
||||||
return client
|
return client
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("client", [True, False], indirect=True)
|
||||||
@pytest.mark.parametrize("path", ["/", "/responses"])
|
@pytest.mark.parametrize("path", ["/", "/responses"])
|
||||||
@needs_pydanticv2
|
@needs_pydanticv2
|
||||||
def test_get(client: TestClient, path: str):
|
def test_get(client: TestClient, path: str):
|
||||||
|
|
@ -40,6 +42,7 @@ def test_get(client: TestClient, path: str):
|
||||||
assert response.json() == {"width": 3, "length": 4, "area": 12}
|
assert response.json() == {"width": 3, "length": 4, "area": 12}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("client", [True, False], indirect=True)
|
||||||
@needs_pydanticv2
|
@needs_pydanticv2
|
||||||
def test_openapi_schema(client: TestClient):
|
def test_openapi_schema(client: TestClient):
|
||||||
response = client.get("/openapi.json")
|
response = client.get("/openapi.json")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue