Skip to content
This repository has been archived by the owner on Mar 7, 2023. It is now read-only.
/ fastapi_paginator Public archive

Paginator for FastAPI

License

Notifications You must be signed in to change notification settings

Accelize/fastapi_paginator

Repository files navigation

Tests codecov PyPI

FastAPI Paginator

Easy to use paginator for FastAPI

Currently, supports only encode/databases as database library and tested with SQlite and PostgreSQL.

Features

  • Simple FastAPI integration.
  • Navigation with page numbers (With total page count returned on first page).
  • Navigation from a specific row (since).
  • Ordering result (On multiple columns).
  • Filtering result using various SQL functions.

Installation

FastAPI Paginator is available on PyPI, so it can be installed like any other Python package.

Example with Pip:

pip install fastapi_paginator

Usage

Routes creations in FastAPI

To use it, you only need to create a fastapi_paginator.Paginator instance linked to the database and routes using fastapi_paginator.PageParameters and fastapi_paginator.Page.

import databases
import fastapi
import pydantic
import sqlalchemy
import fastapi_paginator

# Already existing database, FastAPI application, "item" table, and "item" model
database = databases.Database(f"sqlite:///local.db}")
app = fastapi.FastAPI()

table = sqlalchemy.Table(
    "table",
    sqlalchemy.MetaData(),
    Column("id", sqlalchemy.Integer, primary_key=True),
    Column("name", sqlalchemy.String, nullable=False),
)

class Item(pydantic.BaseModel):
    """Item in database."""

    class Config:
        """Config."""

        orm_mode = True  # Required

    id: int
    name: str


# Create a paginator for the database (Required only once per database)
paginator = fastapi_paginator.Paginator(database)

# Create a paginated route
@app.get("/list")
async def list_data(
    page_parameters: fastapi_paginator.PageParameters = Depends(),
) -> fastapi_paginator.Page[Item]:
    """List data with pagination."""
    return await paginator(table.select(), Item, page_parameters)

Paginated routes usage from clients

Request

Paginator parameters are passed as query parameters, for instance:

GET /list?order_by=id&page=2
Query parameters
page

The page to return.

When page is not specified or equal to 1, the request returns total_page that is the maximum number of pages.

Cannot be used with since.

since

The item from where starting to return the result.

When navigating between successive pages, the next_since returned value should be used as since for the subsequent requests.

Cannot be used with page.

Cannot be used with order_by if not ordering on the field used by since.

order_by

Sort the resulting items by the specified field name.

Order is descending if - is added before the field name, else order is ascending.

This query parameter can be specified multiple time to sort by multiple columns.

Example: "Ordering descending by the created_at column: order_by=-created_at

filter_by

Filter the resulting items.

The query must be in the form field_name operator argument, with:

  • field_name: the name on the field on where apply the filter.
  • operator: one operator from the list bellow.
  • argument: is the operator argument, it can be one or more value separated by , (Depending on the operator), valid values must be a primitive JSON type like numbers, double-quoted strings, true, false and null.

This query parameter can be specified multiple time to filter on more criteria (Using AND logical conjunction).

Available operators:

  • =: Equal to a single value (Also supports null, true and false)
  • <: Lower than a single value.
  • <=: Lower or equal than a single value.
  • >: Greater than a single value.
  • >=: Greater or equal than a single value.
  • between: Between a pair of values (value_1 <= field_value <= value_2).
  • in: Present in a list of one or more values.
  • like: Like a single value (% can be used as wildcard for zero to multiple characters, _ as wildcard for a single character, / can be used as escape character for % and _).
  • ilike: Same as like, but case insensitive.
  • startswith: String representation starts with a single value.
  • endswith: String representation ends with a single value.
  • contains: String representation contains a single value.

Any operator can be negated by adding ! in front of it.

Warning: Depending on your HTTP client, the query parameter value may require to be URL encoded.

Example: Returning only data with a name field that does not start with Product: filter_by=name%20%21like%20%22Product%25%22 (With URL encoded value of: name !like "Product%"')

Response

The response is a JSON dictionnary with the following fields:

  • items: The list returned items.
  • next_since: Next value to use with since query parameter.
  • next_page: Next value to use with page query parameter.
  • total_pages: Total pages, only computed and returned when on page 1

Using alternates JSON libraries

It is possible to override the json.loads function used in all paginator as follows (Example with orjson):

import orjson
import fastapi_paginator


fastapi_paginator.Paginator.json_loads = orjson.loads