Package: piccolo-cursor-pagination
Cursor pagination for Piccolo ORMPiccolois an great ecosystem that helps you createASGIapps faster and easier.LimitOffsetis the default Piccolo pagination used by Piccolo Admin and Piccolo API. This package contains usage of cursor pagination which is suitable for large data sets and has better performance thanLimitOffsetpagination,
but it isstrictly optionalbecause it does not work with the Piccolo Admin and Piccolo API.Installationpipinstallpiccolo_cursor_paginationUsageExample usage ofCursorPagination:importtypingastfromfastapiimportFastAPI,Requestfromfastapi.responsesimportJSONResponsefrompiccolo_api.crud.serializersimportcreate_pydantic_modelfrompiccolo_cursor_pagination.paginationimportCursorPaginationfromhome.tablesimportTaskapp=FastAPI()TaskModelOut:t.Any=create_pydantic_model(table=Task,include_default_columns=True,model_name="TaskModelOut")@app.get("/tasks/",response_model=t.List[TaskModelOut])asyncdeftasks(request:Request,__cursor:t.Optional[str]=None,__previous:t.Optional[str]=None,):try:previous=request.query_params["__previous"]paginator=CursorPagination(cursor=__cursor)rows_result,headers_result=awaitpaginator.get_cursor_rows(Task,request)rows=awaitrows_result.run()headers=headers_resultresponse=JSONResponse({"rows":rows[::-1]},headers={"next_cursor":headers["cursor"],},)exceptKeyError:paginator=CursorPagination(cursor=__cursor)rows_result,headers_result=awaitpaginator.get_cursor_rows(Task,request)rows=awaitrows_result.run()headers=headers_resultresponse=JSONResponse({"rows":rows},headers={"next_cursor":headers["cursor"],},)returnresponse@app.on_event("startup")asyncdefopen_database_connection_pool():try:engine=engine_finder()awaitengine.start_connection_pool()exceptException:print("Unable to connect to the database")@app.on_event("shutdown")asyncdefclose_database_connection_pool():try:engine=engine_finder()awaitengine.close_connection_pool()exceptException:print("Unable to connect to the database")TheCursorPaginationstores the value ofnext_cursorin the response headers.
We can then use thenext_cursorvalue to get new set of results by passingnext_cursorto__cursorquery parameter.Full Piccolo ASGI app is inexamplefolder or you can checkanother examplewith Vue frontend.CustomizationTheCursorPaginationclass has a default value ofpage_sizeandorder_by,
but we can overide this value in constructor to adjust the way the results are displayed.Example of displaying results in ascending order and page size is 10:paginator=CursorPagination(cursor=__cursor,page_size=10,order_by="id")DirectionsTheCursorPaginationhas the ability to move forward and backward.
To go backward we have to pass__previous=yesin the query parameters.Example usage of direction:GET http://localhost:8000/tasks/?__cursor=NA== (forward)
GET http://localhost:8000/tasks/?__cursor=NA==&__previous=yes (backward)LimitationsYou need to be aware that cursor pagination has several trade offs. The cursor must be based on a unique and sequential column in the table and the client can't go to a specific page because there is no concept of the total number of pages or results.WARNING:CursorPaginationuse Piccolo ORMid(PK typeinteger) column as unique and sequential column for pagination.