In fastapi async, I have a complex return model pagination, using sqlalchemy How to nest pagination
Expect results
{
"data": {
"items": [
{
"id": "string",
"cate_name": "string",
"create_time": "2024-01-09T05:35:17.426Z",
"last_modify_time": "2024-01-09T05:35:17.426Z"
}
],
"total": 0,
"page": 1,
"size": 1,
"pages": 0
},
"code":200,
"message":""
}
Actual output
TypeError: Object of type JobCategory is not JSON serializable
#sqlalchemy model
class JobCategory(DBBase):
__tablename__ = 'data_job_category_info'
cate_name = Column("cate_name", String(128), comment="", unique=True)
create_time = Column("create_time", DateTime, server_default=func.now(), comment="")
last_modify_time = Column("last_modify_time", DateTime, server_default=func.now(), onupdate=func.now(),
comment="")
#pydantic model
class JobCateSchema(BaseModelSchema):
cate_name: str = Field(title='', )
create_time: datetime = Field(title='', )
last_modify_time: datetime = Field(title='', )
class Config:
from_attributes = True
class RestfulModel(BaseModel):
code: int
message: str
data: Page[JobCateSchema] # noqa: F401
#router get all
@router.get(path='', dependencies=[Depends(pagination_ctx(Page))], response_model=RestfulModel)
async def ov_job_cate_get_all(session=Depends(router.db_func)):
query = select(JobCategory).order_by(JobCategory.id)
result = await paginate(session, query)
# result = jsonable_encoder(result.scalars(), exclude_unset=True)
return resp_200(data=dict(result))
How do I configure to get the pagination nested in
I had been struggling with a similar issue(raise RuntimeError("Use params or add_pagination")) for a time, and after referring to your code(dependencies=), I was able to solve the problem. I am extremely grateful for your help. I would like to share my solution method:
python 3.11
#...
T = TypeVar('T')
class Result(GenericModel, Generic[T]):
code: int = 0
message: str = 'OK'
time: str = ''
data: Optional[T] = None
#...
@router.get("/product", dependencies=[Depends(pagination_ctx(Page))], response_model=Result[Page[ProductOut]])
async def query(title: str | None = None, db: Session = Depends(xx.get_session)) -> Any:
return result.ok(service.query(title))
#...
I used pydantic's model_dump() method and it passed successfully
@staticmethod
@router.get(path='', dependencies=[Depends(pagination_ctx(PageS))],
response_model=ResultSerializer[PageS[router.schema]])
async def ov_job_cate_get_all(session=Depends(router.db_func)):
query = select(JobCategory).order_by(JobCategory.id)
result = await paginate(session, query)
result = jsonable_encoder(result.model_dump())
return resp_200(data=result)
However, a new problem arises with associated objects
File "F:\Workspace\py_frame\data_preprocess\src\api\job.py", line 110, in ov_job_info_get_all
result = jsonable_encoder(result.model_dump())
│ │ └ <function BaseModel.model_dump at 0x00000243B411E200>
│ └ CustomizedPage(items=[(<src.models.job.JobInfo object at 0x00000243B6FBD090>, '12fasa'), (<src.models.job.JobInfo object at 0...
└ <function jsonable_encoder at 0x00000243B5EC1300>
File "F:\Workspace\py_frame\data_preprocess\venv\Lib\site-packages\fastapi\encoders.py", line 287, in jsonable_encoder
encoded_value = jsonable_encoder(
└ <function jsonable_encoder at 0x00000243B5EC1300>
File "F:\Workspace\py_frame\data_preprocess\venv\Lib\site-packages\fastapi\encoders.py", line 301, in jsonable_encoder
jsonable_encoder(
└ <function jsonable_encoder at 0x00000243B5EC1300>
File "F:\Workspace\py_frame\data_preprocess\venv\Lib\site-packages\fastapi\encoders.py", line 330, in jsonable_encoder
raise ValueError(errors) from e
└ [TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have __dict...
ValueError: [TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have __dict__ attribute')]
class JobInfo(DBBase):
__tablename__ = 'data_job_info'
job_name = Column("job_name", String(128), comment="作业名称", unique=True)
cate_id = Column("cate_id", String(128), comment="作业类别id")
create_time = Column("create_time", DateTime, server_default=func.now(), comment="创建时间")
last_modify_time = Column("last_modify_time", DateTime, server_default=func.now(), onupdate=func.now(),
comment="修改时间")
@staticmethod
@router.get(path='', dependencies=[Depends(pagination_ctx(PageS))],
response_model=ResultSerializer[PageS[JobInfoSchemaSerializer]])
async def ov_job_info_get_all(session=Depends(router.db_func)):
query = select(JobInfo, JobCategory.cate_name).join(JobCategory
, onclause=JobInfo.cate_id == JobCategory.id).order_by(
JobInfo.id)
result = await paginate(session, query)
result = jsonable_encoder(result.model_dump())
print(result)
return resp_200(data=result)
Hi @13129,
Sorry for long response. Could you please try to update pagination_ctx call to:
#router get all
@router.get(path='', dependencies=[Depends(pagination_ctx(Page[JobCateSchema]))], response_model=RestfulModel)
async def ov_job_cate_get_all(session=Depends(router.db_func)):
query = select(JobCategory).order_by(JobCategory.id)
result = await paginate(session, query)
# result = jsonable_encoder(result.scalars(), exclude_unset=True)
return resp_200(data=dict(result))
Is this issue still relevant? Can I somehow help you?
@13129 Any updates? Can I somehow help you?
@13129 Is this issue still relevant?
@13129 I'm closing this issue. Please, reopen it in case this issue is still relevant.