Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to return both Page and Offset #797

Open
dhait opened this issue Aug 23, 2023 · 3 comments
Open

Option to return both Page and Offset #797

dhait opened this issue Aug 23, 2023 · 3 comments
Assignees
Labels
bug Something isn't working

Comments

@dhait
Copy link

dhait commented Aug 23, 2023

I would like to have the page number as well as the offset returned in the response.
Currently I can either choose Page or LimitOffsetPage but not both.

@uriyyo uriyyo self-assigned this Aug 24, 2023
@uriyyo uriyyo added the bug Something isn't working label Aug 24, 2023
@uriyyo
Copy link
Owner

uriyyo commented Aug 24, 2023

Hi @dhait,

Could you please provide examples of what you want to achieve?

@dhait
Copy link
Author

dhait commented Aug 29, 2023

For response_model "Page", we get:

  "items": [ ... ],
  "page": 2,
  "size": 3,
  "pages": 34,
  "total": 100
}

For response_mode "LimitOffsetPage", we get:

{
  "items": [ ... ],
  "limit": 3,
  "offset": 2,
  "total": 100
}

I would like to see:

{
  "items": [ ... ],
  "page": 2,
  "size": 3,
  "offset": 3
  "pages": 34,
  "total": 100
}


Meaning, the first item displayed is "n" offset from the beginning.

I know I could figure it out by multiplying "size" by "page" but it seems like an extra unnecessary step.

Also, it would be a more flexible solution if we could supply EITHER "page" or "offset" as a parameter, depending on the need (notice that "limit" and "size" appear to be the same value).

@uriyyo
Copy link
Owner

uriyyo commented Oct 4, 2024

Hi @dhait,

It has been more than 1 year and I finally managed to get to this issue.

Here is an example using pydantic v2:

from __future__ import annotations

from typing import Optional, TypeVar

from fastapi import FastAPI
from pydantic import computed_field

from fastapi_pagination import Page, add_pagination, paginate
from fastapi_pagination.types import GreaterEqualOne, GreaterEqualZero

T = TypeVar("T")


class CustomPage(Page[T]):
    @computed_field
    def limit(self) -> Optional[GreaterEqualOne]:
        return self.size

    @computed_field
    def offset(self) -> Optional[GreaterEqualZero]:
        if self.page is not None or self.size is not None:
            return self.size * (self.page - 1)

        return None


app = FastAPI()
add_pagination(app)


@app.get("/")
async def route() -> CustomPage[int]:
    return paginate([*range(1_000)])


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app)

This request GET /?size=10&page=4 will give us:

{
    "items": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
    "total": 1000,
    "page": 4,
    "size": 10,
    "pages": 100,
    "limit": 10,
    "offset": 30,
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants