mirror of https://github.com/tiangolo/fastapi.git
✨ Implement response_model_exclude_defaults and response_model_exclude_none (#1166)
* Implemented response_model_exclude_defaults and response_model_exclude_none to be compatible pydantic options.
* 🚚 Rename and invert include_none to exclude_none to keep in sync with Pydantic
Co-authored-by: Lukas Voegtle <lukas.voegtle@sick.de>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
766157bfb4
commit
3397d4d69a
|
|
@ -171,6 +171,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -197,6 +199,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -222,6 +226,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -250,6 +256,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -309,6 +317,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -334,6 +344,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -359,6 +371,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -384,6 +398,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -409,6 +425,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -434,6 +452,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -459,6 +479,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -484,6 +506,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -509,6 +533,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -534,6 +560,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -559,6 +587,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -584,6 +614,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -609,6 +641,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -634,6 +668,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -659,6 +695,8 @@ class FastAPI(Starlette):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -684,6 +722,8 @@ class FastAPI(Starlette):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ def jsonable_encoder(
|
||||||
by_alias: bool = True,
|
by_alias: bool = True,
|
||||||
skip_defaults: bool = None,
|
skip_defaults: bool = None,
|
||||||
exclude_unset: bool = False,
|
exclude_unset: bool = False,
|
||||||
include_none: bool = True,
|
exclude_defaults: bool = False,
|
||||||
|
exclude_none: bool = False,
|
||||||
custom_encoder: dict = {},
|
custom_encoder: dict = {},
|
||||||
sqlalchemy_safe: bool = True,
|
sqlalchemy_safe: bool = True,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
|
|
@ -58,8 +59,12 @@ def jsonable_encoder(
|
||||||
exclude=exclude,
|
exclude=exclude,
|
||||||
by_alias=by_alias,
|
by_alias=by_alias,
|
||||||
exclude_unset=bool(exclude_unset or skip_defaults),
|
exclude_unset=bool(exclude_unset or skip_defaults),
|
||||||
|
exclude_none=exclude_none,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
)
|
)
|
||||||
else: # pragma: nocover
|
else: # pragma: nocover
|
||||||
|
if exclude_defaults:
|
||||||
|
raise ValueError("Cannot use exclude_defaults")
|
||||||
obj_dict = obj.dict(
|
obj_dict = obj.dict(
|
||||||
include=include,
|
include=include,
|
||||||
exclude=exclude,
|
exclude=exclude,
|
||||||
|
|
@ -68,7 +73,8 @@ def jsonable_encoder(
|
||||||
)
|
)
|
||||||
return jsonable_encoder(
|
return jsonable_encoder(
|
||||||
obj_dict,
|
obj_dict,
|
||||||
include_none=include_none,
|
exclude_none=exclude_none,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
custom_encoder=encoder,
|
custom_encoder=encoder,
|
||||||
sqlalchemy_safe=sqlalchemy_safe,
|
sqlalchemy_safe=sqlalchemy_safe,
|
||||||
)
|
)
|
||||||
|
|
@ -87,14 +93,14 @@ def jsonable_encoder(
|
||||||
or (not isinstance(key, str))
|
or (not isinstance(key, str))
|
||||||
or (not key.startswith("_sa"))
|
or (not key.startswith("_sa"))
|
||||||
)
|
)
|
||||||
and (value is not None or include_none)
|
and (value is not None or not exclude_none)
|
||||||
and ((include and key in include) or key not in exclude)
|
and ((include and key in include) or key not in exclude)
|
||||||
):
|
):
|
||||||
encoded_key = jsonable_encoder(
|
encoded_key = jsonable_encoder(
|
||||||
key,
|
key,
|
||||||
by_alias=by_alias,
|
by_alias=by_alias,
|
||||||
exclude_unset=exclude_unset,
|
exclude_unset=exclude_unset,
|
||||||
include_none=include_none,
|
exclude_none=exclude_none,
|
||||||
custom_encoder=custom_encoder,
|
custom_encoder=custom_encoder,
|
||||||
sqlalchemy_safe=sqlalchemy_safe,
|
sqlalchemy_safe=sqlalchemy_safe,
|
||||||
)
|
)
|
||||||
|
|
@ -102,7 +108,7 @@ def jsonable_encoder(
|
||||||
value,
|
value,
|
||||||
by_alias=by_alias,
|
by_alias=by_alias,
|
||||||
exclude_unset=exclude_unset,
|
exclude_unset=exclude_unset,
|
||||||
include_none=include_none,
|
exclude_none=exclude_none,
|
||||||
custom_encoder=custom_encoder,
|
custom_encoder=custom_encoder,
|
||||||
sqlalchemy_safe=sqlalchemy_safe,
|
sqlalchemy_safe=sqlalchemy_safe,
|
||||||
)
|
)
|
||||||
|
|
@ -118,7 +124,8 @@ def jsonable_encoder(
|
||||||
exclude=exclude,
|
exclude=exclude,
|
||||||
by_alias=by_alias,
|
by_alias=by_alias,
|
||||||
exclude_unset=exclude_unset,
|
exclude_unset=exclude_unset,
|
||||||
include_none=include_none,
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
custom_encoder=custom_encoder,
|
custom_encoder=custom_encoder,
|
||||||
sqlalchemy_safe=sqlalchemy_safe,
|
sqlalchemy_safe=sqlalchemy_safe,
|
||||||
)
|
)
|
||||||
|
|
@ -153,7 +160,8 @@ def jsonable_encoder(
|
||||||
data,
|
data,
|
||||||
by_alias=by_alias,
|
by_alias=by_alias,
|
||||||
exclude_unset=exclude_unset,
|
exclude_unset=exclude_unset,
|
||||||
include_none=include_none,
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
custom_encoder=custom_encoder,
|
custom_encoder=custom_encoder,
|
||||||
sqlalchemy_safe=sqlalchemy_safe,
|
sqlalchemy_safe=sqlalchemy_safe,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ def get_openapi_security_definitions(flat_dependant: Dependant) -> Tuple[Dict, L
|
||||||
security_definition = jsonable_encoder(
|
security_definition = jsonable_encoder(
|
||||||
security_requirement.security_scheme.model,
|
security_requirement.security_scheme.model,
|
||||||
by_alias=True,
|
by_alias=True,
|
||||||
include_none=False,
|
exclude_none=True,
|
||||||
)
|
)
|
||||||
security_name = security_requirement.security_scheme.scheme_name
|
security_name = security_requirement.security_scheme.scheme_name
|
||||||
security_definitions[security_name] = security_definition
|
security_definitions[security_name] = security_definition
|
||||||
|
|
@ -310,4 +310,4 @@ def get_openapi(
|
||||||
if components:
|
if components:
|
||||||
output["components"] = components
|
output["components"] = components
|
||||||
output["paths"] = paths
|
output["paths"] = paths
|
||||||
return jsonable_encoder(OpenAPI(**output), by_alias=True, include_none=False)
|
return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True)
|
||||||
|
|
|
||||||
|
|
@ -49,22 +49,43 @@ except ImportError: # pragma: nocover
|
||||||
|
|
||||||
|
|
||||||
def _prepare_response_content(
|
def _prepare_response_content(
|
||||||
res: Any, *, by_alias: bool = True, exclude_unset: bool
|
res: Any,
|
||||||
|
*,
|
||||||
|
by_alias: bool = True,
|
||||||
|
exclude_unset: bool,
|
||||||
|
exclude_defaults: bool = False,
|
||||||
|
exclude_none: bool = False,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
if isinstance(res, BaseModel):
|
if isinstance(res, BaseModel):
|
||||||
if PYDANTIC_1:
|
if PYDANTIC_1:
|
||||||
return res.dict(by_alias=by_alias, exclude_unset=exclude_unset)
|
return res.dict(
|
||||||
|
by_alias=by_alias,
|
||||||
|
exclude_unset=exclude_unset,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return res.dict(
|
return res.dict(
|
||||||
by_alias=by_alias, skip_defaults=exclude_unset
|
by_alias=by_alias, skip_defaults=exclude_unset,
|
||||||
) # pragma: nocover
|
) # pragma: nocover
|
||||||
elif isinstance(res, list):
|
elif isinstance(res, list):
|
||||||
return [
|
return [
|
||||||
_prepare_response_content(item, exclude_unset=exclude_unset) for item in res
|
_prepare_response_content(
|
||||||
|
item,
|
||||||
|
exclude_unset=exclude_unset,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
|
)
|
||||||
|
for item in res
|
||||||
]
|
]
|
||||||
elif isinstance(res, dict):
|
elif isinstance(res, dict):
|
||||||
return {
|
return {
|
||||||
k: _prepare_response_content(v, exclude_unset=exclude_unset)
|
k: _prepare_response_content(
|
||||||
|
v,
|
||||||
|
exclude_unset=exclude_unset,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
|
)
|
||||||
for k, v in res.items()
|
for k, v in res.items()
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
|
|
@ -78,12 +99,18 @@ async 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,
|
||||||
|
exclude_defaults: bool = False,
|
||||||
|
exclude_none: bool = False,
|
||||||
is_coroutine: bool = True,
|
is_coroutine: bool = True,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
if field:
|
if field:
|
||||||
errors = []
|
errors = []
|
||||||
response_content = _prepare_response_content(
|
response_content = _prepare_response_content(
|
||||||
response_content, by_alias=by_alias, exclude_unset=exclude_unset
|
response_content,
|
||||||
|
by_alias=by_alias,
|
||||||
|
exclude_unset=exclude_unset,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
)
|
)
|
||||||
if is_coroutine:
|
if is_coroutine:
|
||||||
value, errors_ = field.validate(response_content, {}, loc=("response",))
|
value, errors_ = field.validate(response_content, {}, loc=("response",))
|
||||||
|
|
@ -103,6 +130,8 @@ async def serialize_response(
|
||||||
exclude=exclude,
|
exclude=exclude,
|
||||||
by_alias=by_alias,
|
by_alias=by_alias,
|
||||||
exclude_unset=exclude_unset,
|
exclude_unset=exclude_unset,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return jsonable_encoder(response_content)
|
return jsonable_encoder(response_content)
|
||||||
|
|
@ -131,6 +160,8 @@ def get_request_handler(
|
||||||
response_model_exclude: Union[SetIntStr, DictIntStrAny] = set(),
|
response_model_exclude: Union[SetIntStr, DictIntStrAny] = set(),
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
dependency_overrides_provider: Any = None,
|
dependency_overrides_provider: Any = None,
|
||||||
) -> Callable:
|
) -> Callable:
|
||||||
assert dependant.call is not None, "dependant.call must be a function"
|
assert dependant.call is not None, "dependant.call must be a function"
|
||||||
|
|
@ -177,6 +208,8 @@ def get_request_handler(
|
||||||
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,
|
||||||
|
exclude_defaults=response_model_exclude_defaults,
|
||||||
|
exclude_none=response_model_exclude_none,
|
||||||
is_coroutine=is_coroutine,
|
is_coroutine=is_coroutine,
|
||||||
)
|
)
|
||||||
response = response_class(
|
response = response_class(
|
||||||
|
|
@ -255,6 +288,8 @@ class APIRoute(routing.Route):
|
||||||
response_model_exclude: Union[SetIntStr, DictIntStrAny] = set(),
|
response_model_exclude: Union[SetIntStr, DictIntStrAny] = set(),
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Optional[Type[Response]] = None,
|
response_class: Optional[Type[Response]] = None,
|
||||||
dependency_overrides_provider: Any = None,
|
dependency_overrides_provider: Any = None,
|
||||||
|
|
@ -326,6 +361,8 @@ class APIRoute(routing.Route):
|
||||||
self.response_model_exclude = response_model_exclude
|
self.response_model_exclude = response_model_exclude
|
||||||
self.response_model_by_alias = response_model_by_alias
|
self.response_model_by_alias = response_model_by_alias
|
||||||
self.response_model_exclude_unset = response_model_exclude_unset
|
self.response_model_exclude_unset = response_model_exclude_unset
|
||||||
|
self.response_model_exclude_defaults = response_model_exclude_defaults
|
||||||
|
self.response_model_exclude_none = response_model_exclude_none
|
||||||
self.include_in_schema = include_in_schema
|
self.include_in_schema = include_in_schema
|
||||||
self.response_class = response_class
|
self.response_class = response_class
|
||||||
|
|
||||||
|
|
@ -352,6 +389,8 @@ class APIRoute(routing.Route):
|
||||||
response_model_exclude=self.response_model_exclude,
|
response_model_exclude=self.response_model_exclude,
|
||||||
response_model_by_alias=self.response_model_by_alias,
|
response_model_by_alias=self.response_model_by_alias,
|
||||||
response_model_exclude_unset=self.response_model_exclude_unset,
|
response_model_exclude_unset=self.response_model_exclude_unset,
|
||||||
|
response_model_exclude_defaults=self.response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=self.response_model_exclude_none,
|
||||||
dependency_overrides_provider=self.dependency_overrides_provider,
|
dependency_overrides_provider=self.dependency_overrides_provider,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -400,6 +439,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -429,6 +470,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -457,6 +500,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -486,6 +531,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -560,6 +607,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude=route.response_model_exclude,
|
response_model_exclude=route.response_model_exclude,
|
||||||
response_model_by_alias=route.response_model_by_alias,
|
response_model_by_alias=route.response_model_by_alias,
|
||||||
response_model_exclude_unset=route.response_model_exclude_unset,
|
response_model_exclude_unset=route.response_model_exclude_unset,
|
||||||
|
response_model_exclude_defaults=route.response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=route.response_model_exclude_none,
|
||||||
include_in_schema=route.include_in_schema,
|
include_in_schema=route.include_in_schema,
|
||||||
response_class=route.response_class or default_response_class,
|
response_class=route.response_class or default_response_class,
|
||||||
name=route.name,
|
name=route.name,
|
||||||
|
|
@ -606,6 +655,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -632,6 +683,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -657,6 +710,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -683,6 +738,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -708,6 +765,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -734,6 +793,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -759,6 +820,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -785,6 +848,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -810,6 +875,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -836,6 +903,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -861,6 +930,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -887,6 +958,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -912,6 +985,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -938,6 +1013,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
@ -963,6 +1040,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_by_alias: bool = True,
|
response_model_by_alias: bool = True,
|
||||||
response_model_skip_defaults: bool = None,
|
response_model_skip_defaults: bool = None,
|
||||||
response_model_exclude_unset: bool = False,
|
response_model_exclude_unset: bool = False,
|
||||||
|
response_model_exclude_defaults: bool = False,
|
||||||
|
response_model_exclude_none: bool = False,
|
||||||
include_in_schema: bool = True,
|
include_in_schema: bool = True,
|
||||||
response_class: Type[Response] = None,
|
response_class: Type[Response] = None,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
|
|
@ -989,6 +1068,8 @@ class APIRouter(routing.Router):
|
||||||
response_model_exclude_unset=bool(
|
response_model_exclude_unset=bool(
|
||||||
response_model_exclude_unset or response_model_skip_defaults
|
response_model_exclude_unset or response_model_skip_defaults
|
||||||
),
|
),
|
||||||
|
response_model_exclude_defaults=response_model_exclude_defaults,
|
||||||
|
response_model_exclude_none=response_model_exclude_none,
|
||||||
include_in_schema=include_in_schema,
|
include_in_schema=include_in_schema,
|
||||||
response_class=response_class or self.default_response_class,
|
response_class=response_class or self.default_response_class,
|
||||||
name=name,
|
name=name,
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,12 @@ class ModelWithAlias(BaseModel):
|
||||||
foo: str = Field(..., alias="Foo")
|
foo: str = Field(..., alias="Foo")
|
||||||
|
|
||||||
|
|
||||||
|
class ModelWithDefault(BaseModel):
|
||||||
|
foo: str = ...
|
||||||
|
bar: str = "bar"
|
||||||
|
bla: str = "bla"
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(
|
@pytest.fixture(
|
||||||
name="model_with_path", params=[PurePath, PurePosixPath, PureWindowsPath]
|
name="model_with_path", params=[PurePath, PurePosixPath, PureWindowsPath]
|
||||||
)
|
)
|
||||||
|
|
@ -121,6 +127,16 @@ def test_encode_model_with_alias():
|
||||||
assert jsonable_encoder(model) == {"Foo": "Bar"}
|
assert jsonable_encoder(model) == {"Foo": "Bar"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_encode_model_with_default():
|
||||||
|
model = ModelWithDefault(foo="foo", bar="bar")
|
||||||
|
assert jsonable_encoder(model) == {"foo": "foo", "bar": "bar", "bla": "bla"}
|
||||||
|
assert jsonable_encoder(model, exclude_unset=True) == {"foo": "foo", "bar": "bar"}
|
||||||
|
assert jsonable_encoder(model, exclude_defaults=True) == {"foo": "foo"}
|
||||||
|
assert jsonable_encoder(model, exclude_unset=True, exclude_defaults=True) == {
|
||||||
|
"foo": "foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_custom_encoders():
|
def test_custom_encoders():
|
||||||
class safe_datetime(datetime):
|
class safe_datetime(datetime):
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,53 @@ class Model(BaseModel):
|
||||||
|
|
||||||
class ModelSubclass(Model):
|
class ModelSubclass(Model):
|
||||||
y: int
|
y: int
|
||||||
|
z: int = 0
|
||||||
|
w: int = None
|
||||||
|
|
||||||
|
|
||||||
|
class ModelDefaults(BaseModel):
|
||||||
|
w: Optional[str] = None
|
||||||
|
x: Optional[str] = None
|
||||||
|
y: str = "y"
|
||||||
|
z: str = "z"
|
||||||
|
|
||||||
|
|
||||||
@app.get("/", response_model=Model, response_model_exclude_unset=True)
|
@app.get("/", response_model=Model, response_model_exclude_unset=True)
|
||||||
def get() -> ModelSubclass:
|
def get() -> ModelSubclass:
|
||||||
return ModelSubclass(sub={}, y=1)
|
return ModelSubclass(sub={}, y=1, z=0)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get(
|
||||||
|
"/exclude_unset", response_model=ModelDefaults, response_model_exclude_unset=True
|
||||||
|
)
|
||||||
|
def get() -> ModelDefaults:
|
||||||
|
return ModelDefaults(x=None, y="y")
|
||||||
|
|
||||||
|
|
||||||
|
@app.get(
|
||||||
|
"/exclude_defaults",
|
||||||
|
response_model=ModelDefaults,
|
||||||
|
response_model_exclude_defaults=True,
|
||||||
|
)
|
||||||
|
def get() -> ModelDefaults:
|
||||||
|
return ModelDefaults(x=None, y="y")
|
||||||
|
|
||||||
|
|
||||||
|
@app.get(
|
||||||
|
"/exclude_none", response_model=ModelDefaults, response_model_exclude_none=True
|
||||||
|
)
|
||||||
|
def get() -> ModelDefaults:
|
||||||
|
return ModelDefaults(x=None, y="y")
|
||||||
|
|
||||||
|
|
||||||
|
@app.get(
|
||||||
|
"/exclude_unset_none",
|
||||||
|
response_model=ModelDefaults,
|
||||||
|
response_model_exclude_unset=True,
|
||||||
|
response_model_exclude_none=True,
|
||||||
|
)
|
||||||
|
def get() -> ModelDefaults:
|
||||||
|
return ModelDefaults(x=None, y="y")
|
||||||
|
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
|
|
@ -31,3 +73,23 @@ client = TestClient(app)
|
||||||
def test_return_defaults():
|
def test_return_defaults():
|
||||||
response = client.get("/")
|
response = client.get("/")
|
||||||
assert response.json() == {"sub": {}}
|
assert response.json() == {"sub": {}}
|
||||||
|
|
||||||
|
|
||||||
|
def test_return_exclude_unset():
|
||||||
|
response = client.get("/exclude_unset")
|
||||||
|
assert response.json() == {"x": None, "y": "y"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_return_exclude_defaults():
|
||||||
|
response = client.get("/exclude_defaults")
|
||||||
|
assert response.json() == {}
|
||||||
|
|
||||||
|
|
||||||
|
def test_return_exclude_none():
|
||||||
|
response = client.get("/exclude_none")
|
||||||
|
assert response.json() == {"y": "y", "z": "z"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_return_exclude_unset_none():
|
||||||
|
response = client.get("/exclude_unset_none")
|
||||||
|
assert response.json() == {"y": "y"}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue