I have the following models:
class BaseMessage(BaseModel):
"""
Base schema for returning a ACK/NACK response.
"""
origin: str = settings.APP_ORIGIN_NAME
message: str
class Success(BaseMessage):
"""
API schema for returning a Success response.
"""
id: str
temp_password: Optional[str] | None
class ACK(BaseModel):
"""
API schema for returning an ACK response.
"""
ACK: Success
and in my POST endpoint, I have this:
@router.post(
path="/",
summary="register a new domain",
description="Registers a new domain.",
response_model=Union[ACK, NACK],
name="domains:create-domain",
status_code=status.HTTP_201_CREATED,
responses={400: {"model": NACK}},
)
async def create_domain(
domain: DomainCreate,
) -> JSONResponse:
try:
instance = Domains(**domain.dict(exclude_unset=True))
instance.domain_hashed_password = get_password_hash(
instance.domain_hashed_password
)
db_instance = await
Domains(**instance.dict(exclude_unset=True)).save()
domain_id: str = str(db_instance.domain_id)
success_text: str = ENDPOINT_MESSAGES["success"]
try:
ack_message = ACK(
message=success_text,
id=domain_id,
temp_password=instance.domain_hashed_password,
)
return JSONResponse(
status_code=status.HTTP_201_CREATED,
content=jsonable_encoder(ack_message),
)
except ValidationError as exc:
print(exc.errors())
except asyncpg.exceptions.UniqueViolationError:
failure_text: str = ENDPOINT_MESSAGES["failure"]
error_text: str = f"{ENDPOINT_MESSAGES['err_unique']} domain_name"
nack_message: dict = APIResponse.nack(failure_text, error_text)
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST, content=nack_message
)
I keep getting..
ACK
field required (type=value_error.missing)
fastapi.exceptions.ResponseValidationError: 1 validation errors:
{'loc': ('response',), 'msg': 'none is not an allowed value', 'type': 'type_error.none.not_allowed'}
...error messages when I POST to the endpoint. It's failing when coming to ack_message, which is not clear to me why as I am providing all the fields. Well at least I think I am. I'm using my ACK model to provide a json response to the end user. I'm clearly doing something wrong. I was expecting ack_message to return:
{
"ACK": {
"origin": "contents of APP_ORIGIN_NAME",
"message": "contents of success_text",
"id": "contents of domain_id",
"temp_password": "contents of domain_hashed_password"
}
}
Solved.
Have solved this based on Victor's answer below. I have to change my ack_message definition to:
ack_message = ACKResponse(
ACK={
"message": success_text,
"id": domain_id,
"temp_password": unhashed_password,
}
)
Well, here I would recommend to rename your entities: ACK is your model name and the name of it's field.
class ACK(BaseModel):
"""
API schema for returning an ACK response.
"""
ACK: Success
So this line will definitely cause an error as value for ACK field was not specified.
ack_message = ACK(
message=success_text,
id=domain_id,
temp_password=instance.domain_hashed_password,
)