Search code examples
fastapiuvicorn

FastAPI pydantic response_model


FastAPI with uvicorn. So far i have everything working fine, now wanted to add extra validation with pydantic and response_model validation. My challange is, the response is a nested object, example:

{
   "name": "always the same",
   "value": ["ACL1", "ACL2", "ACL3"]
}

I have tried to:

class ACL(BaseModel):
    name: str

@app.post(
    "get/acls",
    response_model=List[ACL]
)
def get_acls(credentials: HTTPBasicCredentials = Depends(security)):

But obviously it will fail. How to define correctly the response model so that it's correctly validated ? (and also visible in openapi documentation page ?)

Thanks,


Solution

  • You can use nested models in Pydantic and by by extension also in FastAPI. Like so:

    class ACL(BaseModel):
        name: str
    
    
    class YourResponseModel(BaseModel):
        name: str
        value: list[ACL]
    
    
    @app.post("/get/acls", response_model=YourResponseModel)
    def get_acl():
        return {"name": "always the same", "value": [{"name":"ACL1"}, {"name":"ACL2"}, {"name":"ACL3"}]}
    

    If you don't want nested objects in your value list, then you have to build some logic to parse it. Below is an example of this:

    class ACL(BaseModel):
        name: str
    
    class AnotherResponseModel(BaseModel):
        name: str
        value: list[str]
    
    @app.post("/get/acls2", response_model=AnotherResponseModel)
    def get_acl():
        acls = [ACL(name="ACL1"), ACL(name="ACL2"), ACL(name="ACL3")]
        return {"name": "always the same", "value": [acl.name for acl in acls] }  
    

    Please note, it is bad practice to mix up POST and GET requests (you are defining a POST endpoint, that will 'get' some ACLs for the end user). That is however unrelated to this question.