Browse Source

🐛 Fix FastAPI serialization of Pydantic ORM mode blocking the event loop (#888)

pull/889/head
Sebastián Ramírez 5 years ago
committed by GitHub
parent
commit
7cea84b74c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      fastapi/routing.py

13
fastapi/routing.py

@ -47,7 +47,7 @@ except ImportError: # pragma: nocover
from pydantic.fields import Field as ModelField # type: ignore from pydantic.fields import Field as ModelField # type: ignore
def serialize_response( async def serialize_response(
*, *,
field: ModelField = None, field: ModelField = None,
response: Response, response: Response,
@ -55,6 +55,7 @@ def serialize_response(
exclude: Union[SetIntStr, DictIntStrAny] = set(), exclude: Union[SetIntStr, DictIntStrAny] = set(),
by_alias: bool = True, by_alias: bool = True,
exclude_unset: bool = False, exclude_unset: bool = False,
is_coroutine: bool = True,
) -> Any: ) -> Any:
if field: if field:
errors = [] errors = []
@ -63,7 +64,12 @@ def serialize_response(
response = response.dict(exclude_unset=exclude_unset) response = response.dict(exclude_unset=exclude_unset)
else: else:
response = response.dict(skip_defaults=exclude_unset) # pragma: nocover response = response.dict(skip_defaults=exclude_unset) # pragma: nocover
value, errors_ = field.validate(response, {}, loc=("response",)) if is_coroutine:
value, errors_ = field.validate(response, {}, loc=("response",))
else:
value, errors_ = await run_in_threadpool(
field.validate, response, {}, loc=("response",)
)
if isinstance(errors_, ErrorWrapper): if isinstance(errors_, ErrorWrapper):
errors.append(errors_) errors.append(errors_)
elif isinstance(errors_, list): elif isinstance(errors_, list):
@ -131,13 +137,14 @@ def get_request_handler(
if raw_response.background is None: if raw_response.background is None:
raw_response.background = background_tasks raw_response.background = background_tasks
return raw_response return raw_response
response_data = serialize_response( response_data = await serialize_response(
field=response_field, field=response_field,
response=raw_response, response=raw_response,
include=response_model_include, include=response_model_include,
exclude=response_model_exclude, exclude=response_model_exclude,
by_alias=response_model_by_alias, by_alias=response_model_by_alias,
exclude_unset=response_model_exclude_unset, exclude_unset=response_model_exclude_unset,
is_coroutine=is_coroutine,
) )
response = response_class( response = response_class(
content=response_data, content=response_data,

Loading…
Cancel
Save