pyramid_openapi3 icon indicating copy to clipboard operation
pyramid_openapi3 copied to clipboard

Pagination

Open zupo opened this issue 4 years ago • 0 comments

@miohtama asked me if I have any examples of how to do pagination with pyramid_openapi3.

I don't, but I have some private code that I could potentially share. Ideally, this would be added to README, or be made in to a tutorial. But until this time, let's at least have some information about pagination in this ticket here.

So, firstly, we have this in kafkai.com's openapi.yaml:

        - name: page
          in: query
          description: Page number (default is 1)
          required: false
          schema:
            type: integer
            default: 1
            minimum: 1
        - name: pageSize
          in: query
          description: Limit number of articles returned (default is 20)
          required: false
          schema:
            type: integer
            default: 20
            minimum: 1
            maximum: 100

Then we have the following in the view that handles the /articles endpoint:

page = request.openapi_validated.parameters["query"].get("page", 1)
page_size = request.openapi_validated.parameters["query"].get("pageSize", 20)

return Article.current_user_by(
    request=request,
    page=page,
    page_size=page_size,
    search=search,
    niches=niches,
    ratings=ratings,
    states=states,
    article_ids=article_ids,
    db=request.db,
)

The current_used_by() gets an article from Postgres with SQLAlchemy with the currently logged-in user as context:

@classmethod
def current_user_by(
    cls: t.Type[Article],
    request: Request,
    page: int,
    page_size: int,
    search: str,
    niches: t.List[Niche],
    states: t.List[ArticleState],
    ratings: t.List[Rating],
    article_ids: t.List[str],
    db: Session,
) -> Articles:
    """Get Articles in given states if it matches current user."""

q = query_current_user(cls, request)

[... snip ...]

count = q.count()
results_per_page = q.offset(page_size * (page - 1)).limit(page_size)

return {
    "articles": results_per_page.all(),
    "page": page,
    "pageCount": math.ceil(count / page_size),
    "pageSize": page_size,
    "total": count,
}

And this is it. Hopefully it helps someone. And hopefully someone (me?) finds time in the near future to create an example-app for pagination.

zupo avatar Sep 15 '21 14:09 zupo