I use Fast API to create a web service.
There are following sqlAlchemy models:
class User(Base):
__tablename__ = 'user'
account_name = Column(String, primary_key=True, index=True, unique=True)
email = Column(String, unique=True, index=True, nullable=False)
roles = relationship("UserRole", back_populates="users", lazy=False, uselist=True)
class UserRole(Base):
__tablename__ = 'user_role'
__table_args__ = (UniqueConstraint('role_name', 'user_name', name='user_role_uc'),)
role_name = Column(String, ForeignKey('role.name'), primary_key=True)
user_name = Column(String, ForeignKey('user.account_name'), primary_key=True)
users = relationship("User", back_populates="roles")
Pydantic schemas are below:
class UserRole(BaseModel):
role_name: str
class Config:
orm_mode = True
class UserBase(BaseModel):
account_name: str
email: EmailStr
roles: List[UserRole] = []
class Config:
orm_mode = True
What I have now is:
{
"account_name": "Test.Test",
"email": "[email protected]",
"roles": [
{
"role_name": "all:admin"
},
{
"role_name": "all:read"
}
]
}
What I want to achieve is to get user from api in following structure:
{
"account_name": "Test.Test",
"email": "[email protected]",
"roles": [
"all:admin",
"all:read"
]
}
Is that possible? How should I change schemas to get this?
If you are okay with handling the how to "get user from api" problem statement by modifying the fastapi path definition, see below.
Can you change the response model used by the fastapi path definition in order to handle the desired output format?
Example pydantic response model definition:
class UserResponse(BaseModel):
account_name: str
email: EmailStr
roles: List[str]
Example sqlalchemy query + serialization function:
def get_user_response(user_id) -> UserResponse:
user = User.query.get(user_id)
user_roles = UserRole.query.filter(user=user_id).all()
role_names = [r.role_name for r in user_roles]
response = UserResponse(
account_name=user.account_name,
email=user.email,
roles=role_names
}
return response
Example fastapi path definition:
@app.get("/users/{user_id}", response_model=UserResponse)
async def read_item(user_id):
return get_user_response(user_id)
Considerations:
user_id
for the user queries but this can be replaced with whatever you end up using as your primary key for that table.UserResponse
response model is very similar to UserBase
(you could potentially
subclass UserBase
instead of model to avoid the redefinition of
account_name
and email
, with the tradeoff of having to override the
class' Config
).UserBase
sqlalchemy model object that gets automatically serialized when you query the model from the database
and allows you to eliminate or reduce the code in the get_user_response()
function in the example definition above.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With