Skip to main content

Utilities for developing RESTful API, Open API projects with FastAPI and Python

Project description

ReachCollective / APIs / Utils

Requirements

  • sqlmodel (>=0.0.22,<0.0.23)
  • fastapi (>=0.115.8,<0.116.0)
  • pydantic (>=2.10.6,<3.0.0)

Installation

Poetry

poetry add reachcollective-utils

Pip

pip install reachcollective-utils

Examples

DataGrid

List and paginate data from a model, accepting filters, sorting, and relationships

1. Modify models

Add to_dict() function to each SQL Model, to_dict() gets relationships.

class Post(SQLModel, table=True):
    __tablename__ = "posts"

    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    name: str | None
    status: str | None
    comments: list["Comment"] | None = Relationship(back_populates="post", sa_relationship_kwargs={"lazy": "raise"})

    def to_dict(self, *args, **kwargs):
        data = super().model_dump(*args, **kwargs)
        if 'comments' in self.__dict__:
            data['comments'] = []
            if self.quota_groups:
                data['comments'] = [quota_group.to_dict(*args, **kwargs) for quota_group in self.quota_groups]

        return data


class Comment(SQLModel, table=True):
    __tablename__ = "comments"

    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    description: str | None
    post: Optional["Survey"] = Relationship(back_populates="comments", sa_relationship_kwargs={"lazy": "raise"})

    def to_dict(self, *args, **kwargs):
        data = super().model_dump(*args, **kwargs)
        if 'post' in self.__dict__:
            data['post'] = {}
            if self.survey:
                data['post'] = self.survey.model_dump(*args, **kwargs)

        return data

2. Basic use

# URL: /posts?sort=-created&filter[status]=active&view=paginate


from app.models import Post
from reachcollective.utils import DataGrid

@router.get('/posts', status_code=HTTPStatus.OK)
async def list_(
    request: Request,
    db: AsyncSession = Depends(get_session)
):
    return await DataGrid(db, Post, request).init().get()

2. Custom filters

# URL: /posts?sort=-created&filter[status]=active&filter[name]=demo&view=paginate


from app.models import Post
from reachcollective.utils import DataGrid

@router.get('/posts', status_code=HTTPStatus.OK)
async def list_(
    request: Request,
    db: AsyncSession = Depends(get_session)
):
    datagrid = DataGrid(db, Post, request)
    datagrid.qp.filters.personalize = ['name']
    datagrid.init()

    for key, value in datagrid.params['filters']['customize'].items():
        match key:
            case 'name':
                datagrid.qb.stmt = datagrid.qb.stmt.where(Post.name.ilike(f'%{value}%'))

    return await datagrid.get()

3. Relationships

# URL: /posts?sort=-created&filter[status]=active&view=paginate&with=comments


from app.models import Post
from reachcollective.utils import DataGrid

@router.get('/posts', status_code=HTTPStatus.OK)
async def list_(
    request: Request,
    db: AsyncSession = Depends(get_session)
):
    return await DataGrid(db, Post, request).init().get()

4. Results

{
  "current_page": 1,
  "data": [
    {
      "id": "18a6ac49-cb2f-41c7-ac14-ff5360210c65",
      "name": "demo",
      "status": "active"
    },
    {
      "id": "81f08423-288f-4e74-bcbb-edf5ef37f1fe",
      "name": "demo",
      "status": "active"
    },
    {
      "id": "a017c74f-f0bb-4f65-9faf-36581812bbe7",
      "name": "Test 4",
      "status": "active"
    }
  ],
  "total": 683,
  "per_page": 15,
  "total_pages": 46
}
{
  "current_page": 1,
  "data": [
    {
      "id": "18a6ac49-cb2f-41c7-ac14-ff5360210c65",
      "name": "demo",
      "status": "active",
      "comments": [
        {
          "id": "28a6ac49-cb2f-41c7-ac14-ff5360210c15",
          "name": "Hello"
        },
        {
          "id": "38a6ac49-cb2f-41c7-ac14-ff5360210c25",
          "name": "World"
        }
      ]
    },
    {
      "id": "81f08423-288f-4e74-bcbb-edf5ef37f1fe",
      "name": "demo",
      "status": "active",
      "comments": []
    },
    {
      "id": "a017c74f-f0bb-4f65-9faf-36581812bbe7",
      "name": "Test 4",
      "status": "active",
      "comments": [
        {
          "id": "38a6ac49-cb2f-41c7-ac14-ff5360210c35",
          "name": "Hello"
        }
      ]
    }
  ],
  "total": 683,
  "per_page": 15,
  "total_pages": 46
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

reachcollective_utils-0.1.3.tar.gz (5.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reachcollective_utils-0.1.3-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

Details for the file reachcollective_utils-0.1.3.tar.gz.

File metadata

  • Download URL: reachcollective_utils-0.1.3.tar.gz
  • Upload date:
  • Size: 5.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.12.2 Darwin/24.3.0

File hashes

Hashes for reachcollective_utils-0.1.3.tar.gz
Algorithm Hash digest
SHA256 ad9eef0b1a2b2143e9d0ec75ebd1dbdd3728daf86d28dee8f87c2972b0b3cd69
MD5 8aff69e0e8885cb8b47e6ea23f7eabec
BLAKE2b-256 07c02348d833784d525da863410a2dc7bef346b7dc2bf1df07f7639597f31ab2

See more details on using hashes here.

File details

Details for the file reachcollective_utils-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for reachcollective_utils-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 e7feb7b9c25ee3c0f2c3f7ed242ff5aa84181abcadb403feb3bc400044c95e48
MD5 6d06b1502f985fae2b7ecf5d6962060a
BLAKE2b-256 eba5cf84d9540789fb0497e8b149e55a90cd7be4d7fc1b35205e44b7c5a7b7de

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page