FastAPI pagination

Overview

FastAPI Pagination

License codecov codecov Downloads PYPI PYPI

Installation

# Basic version
pip install fastapi-pagination

# All available integrations
pip install fastapi-pagination[all]

Available integrations:

Example

from fastapi import FastAPI, Depends
from pydantic import BaseModel

from fastapi_pagination import PaginationParams, Page
from fastapi_pagination.paginator import paginate

app = FastAPI()


class User(BaseModel):
    name: str
    surname: str


users = [
    User(name='Yurii', surname='Karabas'),
    # ...
]


@app.get('/users', response_model=Page[User])
async def get_users(params: PaginationParams = Depends()):
    return paginate(users, params)

Example using implicit params

from fastapi import FastAPI, Depends
from pydantic import BaseModel

from fastapi_pagination import Page, pagination_params
from fastapi_pagination.paginator import paginate

app = FastAPI()


class User(BaseModel):
    name: str
    surname: str


users = [
    User(name='Yurii', surname='Karabas'),
    # ...
]


@app.get('/users', response_model=Page[User], dependencies=[Depends(pagination_params)])
async def get_users():
    return paginate(users)
Comments
  • Problem with sqlalchemy .

    Problem with sqlalchemy .

    async def search_offertypes(order: bool = False, parameter: OffertypeList = Depends(), db: Session = Depends(get_db)) -> Any: return paginate(db.query(OfferType))

    output:

    TypeError: object of type 'Query' has no len()

    question 
    opened by ScrimForever 16
  • LimitOffsetParams don't work

    LimitOffsetParams don't work

    This way pagination works fine:

    from fastapi_pagination import pagination_params
    

    When switching to limit-offset version:

    from fastapi_pagination.limit_offset import pagination_params
    

    same code and adjusted request fail with: "Page should be used with PaginationParams" Request:

    http://0.0.0.0:8080/api/v1/call_records?date_from=2021-01-01&date_till=2021-02-01&limit=50&offset=0
    

    Endpoint:

    @router.get('/call_records', response_model=Page[CallRecord], dependencies=[Depends(pagination_params)], tags=['calls'])
    @handle_exceptions
    async def get_call_records(date_from: datetime.date, date_till: datetime.date):
        records = await core.get_call_records(database, date_from, date_till, None)
        page = paginate(records)
        return page
    
    documentation question 
    opened by kamikaze 15
  • pagination of records with datetimes does not include timezone (UTC) Z letter

    pagination of records with datetimes does not include timezone (UTC) Z letter

    My DB stores "datetime without timezone". When I do a query without the pagination librayr and serialize to pydantic models via parse_obj_as, the daettime string generated includes Z at the end. If I use the same query but use paginate(session, query), the paged results do not specify a timezone at the end.

    I'm on fastapi-pagination v0.9.1

    bug question 
    opened by stealthrabbi 12
  • Paginate inner model field

    Paginate inner model field

    Great library, thanks!

    How would you go about using it on an endpoint which doesn't directly return a sequence, but a model in which a field is the sequence to paginate, e.g.:

    class ResponseType(BaseModel):
        other_data: int
        data_to_paginate: Sequence[str]
    
    question 
    opened by davidbrochart 12
  • Wrong Pagination items from query , on various pages, for query with Out of Order Items

    Wrong Pagination items from query , on various pages, for query with Out of Order Items

    I am getting the wrong pagination items on various pages, which is a bit concerning.

    here is the query:

    SELECT comments.id AS comments_id, comments.cid AS comments_cid, comments.text AS comments_text, comments.time AS comments_time, comments.is_owner AS comments_is_owner, comments.video_id AS comments_video_id, comments.analysis_id AS comments_analysis_id, comments.author AS comments_author, comments.channel AS comments_channel, comments.votes AS comments_votes, comments.reply_count AS comments_reply_count, comments.sentiment AS comments_sentiment, comments.has_sentiment_negative AS comments_has_sentiment_negative, comments.has_sentiment_positive AS comments_has_sentiment_positive, comments.has_sentiment_neutral AS comments_has_sentiment_neutral, comments.is_reply AS comments_is_reply, comments.is_word_spammer AS comments_is_word_spammer, comments.is_my_spammer AS comments_is_my_spammer, comments.is_most_voted_duplicate AS comments_is_most_voted_duplicate, comments.duplicate_count AS comments_duplicate_count, comments.copy_count AS comments_copy_count, comments.is_copy AS comments_is_copy, comments.is_bot_author AS comments_is_bot_author, comments.has_fuzzy_duplicates AS comments_has_fuzzy_duplicates, comments.fuzzy_duplicate_count AS comments_fuzzy_duplicate_count, comments.is_bot AS comments_is_bot, comments.is_human AS comments_is_human, comments.external_phone_numbers AS comments_external_phone_numbers, comments.keywords AS comments_keywords, comments.phrases AS comments_phrases, comments.custom_keywords AS comments_custom_keywords, comments.custom_phrases AS comments_custom_phrases, comments.external_urls AS comments_external_urls, comments.has_external_phone_numbers AS comments_has_external_phone_numbers, comments.text_external_phone_numbers AS comments_text_external_phone_numbers, comments.unicode_characters AS comments_unicode_characters, comments.unicode_alphabet AS comments_unicode_alphabet, comments.unicode_emojis AS comments_unicode_emojis, comments.unicode_digits AS comments_unicode_digits, comments.has_keywords AS comments_has_keywords, comments.has_phrases AS comments_has_phrases, comments.has_unicode_alphabet AS comments_has_unicode_alphabet, comments.has_unicode_emojis AS comments_has_unicode_emojis, comments.has_unicode_characters AS comments_has_unicode_characters, comments.has_unicode_too_many AS comments_has_unicode_too_many, comments.has_unicode_digits AS comments_has_unicode_digits, comments.has_custom_keywords AS comments_has_custom_keywords, comments.has_custom_phrases AS comments_has_custom_phrases, comments.has_unicode_non_english AS comments_has_unicode_non_english, comments.has_external_urls AS comments_has_external_urls, comments.has_duplicates AS comments_has_duplicates, comments.has_copies AS comments_has_copies, comments.created_at AS comments_created_at 
    FROM comments 
    WHERE comments.analysis_id = %(analysis_id_1)s ORDER BY comments.votes DESC
    

    Here is the function:

    @router.get("/{analysis_id}/comments", status_code=status.HTTP_200_OK, )
    async def read_comments(analysis_id: str, params: Params = Depends(), sort: str | None = None, filters: str | None = None, search_query: str | None = None,
                            current_user: schemas.User = Depends(oauth2.get_current_active_user), db: Session = Depends(database.get_db),
                            api_key: APIKey = Depends(apikey.get_api_key)):
    
     # Sort
        if sort == 'top' or sort != 'recent':
            query = db.query(models.Comment).order_by(models.Comment.votes.desc())
        else:
            query = db.query(models.Comment).order_by(models.Comment.created_at.desc())
    
        return paginate(
            query,
            params,
        )
    
    

    The query can include various filters and is dynamic.

    The items on various pages overlap with on item on other pages. Here is one item on page 5: image and then the same id/item is on page 2: image

    The IDs are out of order because they are sorted by voted items and not the id field. If sorted by the id field then there is no issue.

    So to replicate this do an order_by another field.

    bug 
    opened by ikkysleepy 11
  • custom parameter to replace

    custom parameter to replace "total" field on Page

    I'm trying to replace the "total" field in fastapi-pagination because I'm querying a dynamodb database that has query limitations.

    The database is limited to showing more than 1000 rows. To be able to see all the results without querying I have to create a function that counts all the rows in the table and pass it to the "total" field.

    Is this possible and if yes, how?

    Any help appreciated.

    documentation 
    opened by Sibbern 8
  • Unalbe to import pagination_params

    Unalbe to import pagination_params

    Earlier when I have installed fastapi-pagination it was 0.5.2 it was working fine

    Today I installed then the version is .0.6.1

    now it produces following error.

    from fastapi_pagination import pagination_params ImportError: cannot import name 'pagination_params' from 'fastapi_pagination'

    when I am trying to import :

    from fastapi_pagination import pagination_params from fastapi_pagination.paginator import paginate from fastapi_pagination import PaginationParams, Page

    Same code is working fine in 0.5.2

    Any help is appreciated.

    question 
    opened by shyamsukhamit 8
  • SQLModel: Many-to-many relationship data dropped when paginating

    SQLModel: Many-to-many relationship data dropped when paginating

    This is similar to https://github.com/uriyyo/fastapi-pagination/issues/294

    However, when using SQLModel the relationship data is dropped. I'm always getting null for tags in my FastAPI response.

    The queries seem fine. If I remove pagination, a simple unpaginated List of CustomerViews contains the tags. Maybe I'm doing something wrong with the model setup?

    Excuse typos / weirdness. I had to pull this out of a large project and pare it down to make it readable.

    
    # Relevant schema classes ----------------------------------------------
    
    class CustomerViewToTagBase(SQLModel, TimeStampMixin):
        customer_view: int = Field(foreign_key="customer_view.id", primary_key=True)
        tag: int = Field(foreign_key="tag.id", primary_key=True)
    
    class CustomerViewToTag(CustomerViewToTagBase, table=True):
        __tablename__ = "customer_view_to_tag"
    
    class TagBase(SQLModel):
        name: str
    
    class Tag(TagBase, table=True):
        __tablename__ = "tag"
        id: Optional[int] = Field(default=None, primary_key=True)
        customer_views: List["CustomerView"] = Relationship(back_populates="tags", link_model=CustomerViewToTag)
    
    class CustomerViewBase(SQLModel):
        __tablename__ = "customer_view"
        name: Optional[str] = Field(default=None)
    
    class CustomerView(CustomerViewBase, table=True):
        id: Optional[int] = Field(default=None, primary_key=True)
        tags: List["Tag"] = Relationship(back_populates="customer_views", link_model=CustomerViewToTag)
    
    # For FastAPI
    class CustomerViewWithTag(CustomerViewBase):
        id: int
        tags: Optional[List[Tag]]
    
        # I have no idea if this is necessary, I added it based on the linked issue above #294 
        class Config:
            orm_mode = True
    
    
    # Router ------------------------------------------------------------------------
    
    @router.get("/withtags", response_model=Page[CustomerViewWithTag], status_code=200)
    async def get_customer_views_with_tags(
            db_session: AsyncSession = Depends(get_db_session),
            params: Params = Depends(),
            filter: Optional[str] = None
        ):
        async with db_session as db:
            customerviews_query = select(CustomerView).order_by(CustomerView.id).options(selectinload(CustomerView.tags))
    
            if filter is not None:
                customerviews_query = customerviews_query.filter(
                        CustomerView.name.ilike('%' + filter + '%')
                )
    
            # Switching the response_model to a List and the following code makes the relationship work properly
            # res = await db.execute(customerviews_query)
            # return res.scalars().all()
            return await paginate(session=db, query=customerviews_query, params=params)
    
    
    question 
    opened by thebleucheese 6
  • Pagination fails for a generator because

    Pagination fails for a generator because "total" is not allowed to be None

    Hi :) Thank you for the library. I am facing an issue which I hope you could help me out.

    This is my script

    from fastapi_pagination import Page, Params, iterables
    from fastapi import Depends, FastAPI
    from pydantic import BaseModel
    
    
    class User(BaseModel):
        name: str
    
    app = FastAPI()
    
    users = (User(name="Name_"+str(i)) for i in range(1000))
    
    @app.get(
        "/",
        response_model=Page[User],
    )
    def route(params: Params = Depends()):
        #return iterables.paginate(users, params, 1000) # this works
        return iterables.paginate(users, params)
    
    

    Here's the traceback

    WARNING:  StatReload detected file change in 'pag.py'. Reloading...
    INFO:     Shutting down
    INFO:     Waiting for application shutdown.
    INFO:     Application shutdown complete.
    INFO:     Finished server process [40003]
    INFO:     Started server process [40028]
    INFO:     Waiting for application startup.
    INFO:     Application startup complete.
    INFO:     127.0.0.1:54750 - "GET /?page=2&size=50 HTTP/1.1" 500 Internal Server Error
    ERROR:    Exception in ASGI application
    Traceback (most recent call last):
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/uvicorn/protocols/http/h11_impl.py", line 396, in run_asgi
        result = await app(self.scope, self.receive, self.send)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
        return await self.app(scope, receive, send)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/fastapi/applications.py", line 199, in __call__
        await super().__call__(scope, receive, send)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/applications.py", line 111, in __call__
        await self.middleware_stack(scope, receive, send)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/middleware/errors.py", line 181, in __call__
        raise exc from None
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/middleware/errors.py", line 159, in __call__
        await self.app(scope, receive, _send)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/exceptions.py", line 82, in __call__
        raise exc from None
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/exceptions.py", line 71, in __call__
        await self.app(scope, receive, sender)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/routing.py", line 566, in __call__
        await route.handle(scope, receive, send)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/routing.py", line 227, in handle
        await self.app(scope, receive, send)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/routing.py", line 41, in app
        response = await func(request)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/fastapi/routing.py", line 201, in app
        raw_response = await run_endpoint_function(
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/fastapi/routing.py", line 150, in run_endpoint_function
        return await run_in_threadpool(dependant.call, **values)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/starlette/concurrency.py", line 34, in run_in_threadpool
        return await loop.run_in_executor(None, func, *args)
      File "/usr/lib/python3.9/concurrent/futures/thread.py", line 52, in run
        result = self.fn(*self.args, **self.kwargs)
      File "/home/kishore/kishore_repositories/hx/hawkeye-poc/./pag.py", line 27, in route
        return iterables.paginate(users, params)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/fastapi_pagination/iterables.py", line 33, in paginate
        return create_page(items, total, params)  # type: ignore
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/fastapi_pagination/api.py", line 36, in create_page
        return page_type.get().create(items, total, params)
      File "/home/kishore/.cache/pypoetry/virtualenvs/hawkeye-xjjpv_py-py3.9/lib/python3.9/site-packages/fastapi_pagination/default.py", line 40, in create
        return cls(
      File "pydantic/main.py", line 406, in pydantic.main.BaseModel.__init__
    pydantic.error_wrappers.ValidationError: 1 validation error for Page
    total
      none is not an allowed value (type=type_error.none.not_allowed)
    

    https://github.com/uriyyo/fastapi-pagination/blob/31a286209878e3caf2b666004fc557ec2e6e3ab3/fastapi_pagination/default.py#L34

    https://github.com/uriyyo/fastapi-pagination/blob/31a286209878e3caf2b666004fc557ec2e6e3ab3/fastapi_pagination/bases.py#L89

    The above two lines seem to be causing the problem if I'm not wrong.

    Is it possible to have it as an optional argument total: int = None or total: conint(ge=0) = None # type: ignore ?

    If you see my example, it works when I pass the length of the generator

    return iterables.paginate(users, params, 1000) # this works
    

    My use case is returning all rows from an OLAP. Since the number of rows are around a Million, I would be returning the rows using a generator and returning maybe 50-100 rows at a time to avoid memory overhead

    I can see 2 ways to solve this.

    1. Find the length of the generator and pass it to iterables.paginate and not bother modifying fastapi-pagination. ( or for this particular use case I could get the row count and pass it without bothering to find the length of the generator)
    2. Modify fastapi-pagination to handle None as a possible parameter for total pages.

    Please let me know your thoughts. I hope this is a reasonable feature to ask.

    opened by kishvanchee 6
  • How to use paginate with sqlalchemy new query syntax

    How to use paginate with sqlalchemy new query syntax

    Hi

    I'm trying to migrate to Sqlalchemy 1.4.23 and activate the new query syntax. But can't figure out how to use paginate function with it.

    fastapi-pagination==0.8.3

    from sqlalchemy.future import select
    from models import UserModel
    
    
    class User:
        def _init__(self, db_session):
            self.db_session = session
    
        def get_users():
            return select(UserModel)
    

    The endpoint looks like this:

    from fastapi_pagination.ext.sqlalchemy import paginate
    from fastapi_pagination import Page, Params
    
    @router.get('/get-users')
    def get_users(self, 
                           page_schema: PaginationParams = Depends(),
                           db_session: Session = Depends(get_request_db)) -> Page[UserSchema]:
        users = User(db_session).get_users()
    
        return paginate(users, page_schema)
    

    I'm getting this error:

    image

    Also tried:

    from sqlalchemy.future import select
    from models import UserModel
    
    
    class User:
        def _init__(self, db_session):
            self.db_session = session
    
        def get_users():
            return self.db_session.execute(select(UserModel))
    

    but got this:

    image

    enhancement 
    opened by rafa761 6
  • Fastapi-pagination Throwing error on linux instance.

    Fastapi-pagination Throwing error on linux instance.

    I am working on a project where pagination is working fine but as i take a step forward to host it on AWS EC2 ubuntu instance, it started throwing error like

    ERROR: Could not find a version that satisfies the requirement fastapi-pagination==0.5.1 ERROR: No matching distribution found for fastapi-pagination==0.5.1

    It also worked fine on heroku, i am not able to understand that this problem is from AWS or package.

    question 
    opened by alam-mahtab 6
  • fastapi-pagination [databases] --> DeprecationWarning

    fastapi-pagination [databases] --> DeprecationWarning

    image

    • test of only 1 funtion with pagination

    in file of crud:

       from fastapi_pagination.ext.databases import paginate
    
       async def smx():
           -- logic --
           return await paginate(db=db, query=table.select().where(), params=params)
    

    Deprication was fixed by Encode/Databases in last versions

    bug 
    opened by vadikam100500 0
  • 📃 Update docs

    📃 Update docs

    Documentation should be updated.

    Topics that should be covered:

    • [ ] General information
    • [ ] Customization
    • [ ] Features
    • [ ] Integrations
    • [ ] Examples

    Related issue: #273 #269 #264

    documentation help wanted good first issue 
    opened by uriyyo 2
Releases(0.11.1)
A minimal Streamlit app showing how to launch and stop a FastAPI process on demand

Simple Streamlit + FastAPI Integration A minimal Streamlit app showing how to launch and stop a FastAPI process on demand. The FastAPI /run route simu

Arvindra 18 Jan 02, 2023
FastAPI native extension, easy and simple JWT auth

fastapi-jwt FastAPI native extension, easy and simple JWT auth

Konstantin Chernyshev 19 Dec 12, 2022
Prometheus exporter for several chia node statistics

prometheus-chia-exporter Prometheus exporter for several chia node statistics It's assumed that the full node, the harvester and the wallet run on the

30 Sep 19, 2022
Easy and secure implementation of Azure AD for your FastAPI APIs 🔒

FastAPI-Azure-auth Azure AD Authentication for FastAPI apps made easy. 🚀 Description FastAPI is a modern, fast (high-performance), web framework for

Intility 216 Dec 27, 2022
Code Specialist 27 Oct 16, 2022
Ansible Inventory Plugin, created to get hosts from HTTP API.

ansible-ws-inventory-plugin Ansible Inventory Plugin, created to get hosts from HTTP API. Features: Database compatible with MongoDB and Filesystem (J

Carlos Neto 0 Feb 05, 2022
Ready-to-use and customizable users management for FastAPI

FastAPI Users Ready-to-use and customizable users management for FastAPI Documentation: https://fastapi-users.github.io/fastapi-users/ Source Code: ht

FastAPI Users 2.3k Dec 30, 2022
Prometheus exporter for Starlette and FastAPI

starlette_exporter Prometheus exporter for Starlette and FastAPI. The middleware collects basic metrics: Counter: starlette_requests_total Histogram:

Steve Hillier 225 Jan 05, 2023
fastapi-mqtt is extension for MQTT protocol

fastapi-mqtt MQTT is a lightweight publish/subscribe messaging protocol designed for M2M (machine to machine) telemetry in low bandwidth environments.

Sabuhi 144 Dec 28, 2022
✨️🐍 SPARQL endpoint built with RDFLib to serve machine learning models, or any other logic implemented in Python

✨ SPARQL endpoint for RDFLib rdflib-endpoint is a SPARQL endpoint based on a RDFLib Graph to easily serve machine learning models, or any other logic

Vincent Emonet 27 Dec 19, 2022
Asynchronous event dispatching/handling library for FastAPI and Starlette

fastapi-events An event dispatching/handling library for FastAPI, and Starlette. Features: straightforward API to emit events anywhere in your code ev

Melvin 238 Jan 07, 2023
API using python and Fastapi framework

Welcome 👋 CFCApi is a API DEVELOPMENT PROJECT UNDER CODE FOR COMMUNITY ! Project Walkthrough 🚀 CFCApi run on Python using FASTapi Framework Docs The

Abhishek kushwaha 7 Jan 02, 2023
A Python framework to build Slack apps in a flash with the latest platform features.

Bolt for Python A Python framework to build Slack apps in a flash with the latest platform features. Read the getting started guide and look at our co

SlackAPI 684 Jan 09, 2023
This project shows how to serve an ONNX-optimized image classification model as a web service with FastAPI, Docker, and Kubernetes.

Deploying ML models with FastAPI, Docker, and Kubernetes By: Sayak Paul and Chansung Park This project shows how to serve an ONNX-optimized image clas

Sayak Paul 104 Dec 23, 2022
🍃 A comprehensive monitoring and alerting solution for the status of your Chia farmer and harvesters.

chia-monitor A monitoring tool to collect all important metrics from your Chia farming node and connected harvesters. It can send you push notificatio

Philipp Normann 153 Oct 21, 2022
Simple web app example serving a PyTorch model using streamlit and FastAPI

streamlit-fastapi-model-serving Simple example of usage of streamlit and FastAPI for ML model serving described on this blogpost and PyConES 2020 vide

Davide Fiocco 291 Jan 06, 2023
Complete Fundamental to Expert Codes of FastAPI for creating API's

FastAPI FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3 based on standard Python type hints. The key featu

Pranav Anand 1 Nov 28, 2021
FastAPI framework plugins

Plugins for FastAPI framework, high performance, easy to learn, fast to code, ready for production fastapi-plugins FastAPI framework plugins Cache Mem

RES 239 Dec 28, 2022
FastAPI CRUD template using Deta Base

Deta Base FastAPI CRUD FastAPI CRUD template using Deta Base Setup Install the requirements for the CRUD: pip3 install -r requirements.txt Add your D

Sebastian Ponce 2 Dec 15, 2021
Slack webhooks API served by FastAPI

Slackers Slack webhooks API served by FastAPI What is Slackers Slackers is a FastAPI implementation to handle Slack interactions and events. It serves

Niels van Huijstee 68 Jan 05, 2023