Utilities for developing RESTful API, Open API projects with FastAPI and Python
Project description
ReachCollective / APIs / Utils
Utilities for developing RESTful API, Open API projects with FastAPI and Python
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
Components
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: Post | None = 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.datagrid 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.datagrid 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.datagrid 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
}
Query Params
Parses, sanitizes and formats data from a URL query params. NOTE: Does not require sqlmodel
# URL: /query-params?sort=-last_updated&with=survey,profile&size=2&filter[name]=young&filter[status]=active|deactivate&filter[survey_id]=994c231c|8a900c77&view=paginate
from reachcollective.utils.datagrid import QueryParams
from reachcollective.utils import APIRender
@router.get('/query-params')
async def test_query_params(request: Request):
try:
return QueryParams(request).get()
except HTTPException as e:
return APIRender.error(e.detail, e.status_code)
Results
{
"filters": {
"init": {},
"equals": {
"name": "young",
"status": [
"active",
"deactivate"
],
"survey_id": [
"994c231c",
"8a900c77"
]
},
"customize": {}
},
"with": [
"survey",
"profile"
],
"sort": [
{
"col": "last_updated",
"dir": "desc",
"by": "-last_updated"
}
],
"view": "paginate",
"page": 1,
"size": 2
}
APIRender
Centralizes fastAPI and third-party responses into a single class. Used in FastaPI routes. NOTE: Require pydantic
from reachcollective.utils import APIRender
@router.get('/api-render')
async def test_query_params(request: Request):
try:
# TODO: Your code here
except HTTPException as e:
return APIRender.error(e.detail, e.status_code)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reachcollective_utils-0.1.11.tar.gz.
File metadata
- Download URL: reachcollective_utils-0.1.11.tar.gz
- Upload date:
- Size: 6.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.13.5 Darwin/24.5.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27dd5fdcaa274ea7d112f5bcf4cf3ce72b89f8f8b3fe38ba2f53d2e30fc76dce
|
|
| MD5 |
484eba391699f0fac75b9e02e34f01ff
|
|
| BLAKE2b-256 |
f0c559b95c3ddbb5fef9251ebdefa2805a81a1174d50632460c0363b46c587d4
|
File details
Details for the file reachcollective_utils-0.1.11-py3-none-any.whl.
File metadata
- Download URL: reachcollective_utils-0.1.11-py3-none-any.whl
- Upload date:
- Size: 9.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.13.5 Darwin/24.5.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e615ab938628f4df595a0494e3b1cee78e694e5c18435dafd60e3642786052d
|
|
| MD5 |
341ddc7f8fd27e65751d095604408a09
|
|
| BLAKE2b-256 |
d1dfbeb9a1f969090d4dded9707b8ed0d0e1d2fe03305dea7cdd05b681a9a3f9
|