简体   繁体   中英

Conditionally set FastAPI response model for route

I'm trying to return a list of objects of type Company, including only "approved" ones, and with more or less attributes depending on whether the user requesting the list is a superuser or a regular user. This is my code so far:

@router.get("/", response_model=List[schema.CompanyRegularUsers])
def get_companies(db: Session = Depends(get_db), is_superuser: bool = Depends(check_is_superuser)):
    """
    If SU, also include sensitive data.
    """
    if is_superuser:
        return crud.get_companies_admin(db=db)
    return crud.get_companies_user(db=db)
#

The function correctly returns the objects according to request (ie., only is_approved=True companies if a regular request, and both is_approved=True and is_approved=False if requested by a superuser. Problem is, both cases use schema.CompanyRegularUsers , and I'd like to use schema.CompanySuperusers when SU's make the request.

How can I achieve that feature? Ie, is there a way to conditionally set the response_model property of the decorator function?

I've tried using JSONResponse and calling Pydantic's schema.CompanySuperusers.from_orm() , but it won't work with a list of Companies...

You can try to use Union type operator.

Your code would become

from typing import Union

@router.get("/", response_model=List[Union[schema.CompanyRegularUsers, schema.CompanySuperUser]])

this way, you specify as response model a list of either schema.CompanyRegularUsers or schema.CompanySuperUser

Let me know if it works, since I didn't test it

I ended up solving the riddle by returning a custom JSONResponse. It doesn't show up in the automatic documentation, but I think I can tackle that down the road. Code is as follows, in case it helps someone else:

...
from pydantic import parse_obj_as
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_conder
...

@router.get("/", response_model=List[schema.CompanyRegularUsers])
def get_companies(db: Session = Depends(get_db), is_superuser: bool = Depends(check_is_superuser)):
    """
    If SU, also include sensitive data.
    """
    if is_superuser:
        companies = parse_obj_as(List[schema.CompanyAdmin], crud.get_companies_admin(db=db))
        return JSONResponse(jsonable_encoder(companies))
    return crud.get_companies_user(db=db)

So, in the is_admin branch, the path operation calls pydantic's parse_obj_as in order to map the list of objects returned by SQLAlchemy's query as to (a list of) CompanyAdmin objects. Then, it uses jsonable_encoder , the encoder FastAPI uses under the hood for every default response, to serialize the list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM