Search code examples
pythonapifastapiuvicorn

Return Response model as a value in JSON response


I would like to make that my query returns something like that:

{"message": "OK",
 "data": {
      "username": "string",
      "pseudo": "string",
      "email": "string"}
}

But i cant make my model return inside JSON i am only capable of returning ONLY the model so it gives that :

{
 "username": "string",
 "pseudo": "string",
 "email": "string"
}

That is the code that i tried to run to get the first code snippet

@app.post("/", response_model=_models.UserOut, status_code=status.HTTP_201_CREATED)
def postUser(userPost: _models.UserIn):
  if not userPost.regex_check_email(userPost.email):
    raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Email: {userPost.email} not valid format")
  if not userPost.regex_check_username(userPost.username):
    raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
                        detail=f"Username: {userPost.username} not valid format")
  else:
    db_user.append(userPost)
    return {"message": "OK",
            "data": userPost}

and my models :

class UserOut(BaseModel):
  username: str
  pseudo: Optional[str] = None
  email: str


class UserIn(UserOut):
  username: str
  pseudo: Optional[str] = None
  email: str
  password: str

  def regex_check_email(self, email):
    match = re.match(email_regex, email)
    is_match_email = bool(match)
    return is_match_email

  def regex_check_username(self, username):
    match = re.match(username_regex, username)
    is_match_username = bool(match)
    return is_match_username

this only returns me

pydantic.error_wrappers.ValidationError: 2 validation errors for UserOut response -> username field required (type=value_error.missing) response -> email field required (type=value_error.missing)

It would be great if u could help me and tell me why i was failing, i think i did not understood everything about response models. Thanks.


Solution

  • In the header of your POST handler you are using

    @app.post("/", response_model=_models.UserOut ...)
    ...
    

    So when you try to return something that doesn't match the UserOut model it returns an error. Create a model that defines your message and data structure as desired and use that as the response_model

    Happy coding

    Edit: Have you tried using something like this: (python 3.10+)

    class UserData(BaseModel):
      username: str
      pseudo: Optional[str] = None
      email: str
    
    class UserOut(BaseModel):
      message: str
      data: UserData | None = None
    

    When in doubt, the official documentation usually has examples.