Name | FastAPI-JSONAPI JSON |
Version |
2.8.0
JSON |
| download |
home_page | None |
Summary | FastAPI extension to create REST web api according to JSON:API 1.0 specification with FastAPI, Pydantic and data provider of your choice (SQLAlchemy, Tortoise ORM) |
upload_time | 2024-04-27 13:27:10 |
maintainer | None |
docs_url | None |
author | None |
requires_python | None |
license | None |
keywords |
fastapi
json:api
jsonapi
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
|
[![Last Commit](https://img.shields.io/github/last-commit/mts-ai/FastAPI-JSONAPI?style=for-the-badge)](https://github.com/mts-ai/FastAPI-JSONAPI)
[![PyPI](https://img.shields.io/pypi/v/fastapi-jsonapi?label=PyPI&style=for-the-badge)](https://pypi.org/project/FastAPI-JSONAPI/)
[![](https://img.shields.io/pypi/pyversions/FastAPI-JSONAPI?style=for-the-badge)](https://pypi.org/project/FastAPI-JSONAPI/)
[![](https://img.shields.io/github/license/ycd/manage-fastapi?style=for-the-badge)](https://pypi.org/project/FastAPI-JSONAPI/)
[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/mts-ai/FastAPI-JSONAPI/testing.yml?style=for-the-badge)](https://github.com/mts-ai/FastAPI-JSONAPI/actions)
[![Read the Docs](https://img.shields.io/readthedocs/fastapi-jsonapi?style=for-the-badge)](https://fastapi-jsonapi.readthedocs.io/en/latest/)
[![Codecov](https://img.shields.io/codecov/c/github/mts-ai/FastAPI-JSONAPI?style=for-the-badge)](https://codecov.io/gh/mts-ai/FastAPI-JSONAPI)
[![📖 Docs (gh-pages)](https://github.com/mts-ai/FastAPI-JSONAPI/actions/workflows/documentation.yaml/badge.svg)](https://mts-ai.github.io/FastAPI-JSONAPI/)
# FastAPI-JSONAPI
FastAPI-JSONAPI is a FastAPI extension for building REST APIs.
Implementation of a strong specification [JSONAPI 1.0](http://jsonapi.org/).
This framework is designed to quickly build REST APIs and fit the complexity
of real life projects with legacy data and multiple data storages.
## Architecture
![docs/img/schema.png](docs/img/schema.png)
## Install
```bash
pip install FastAPI-JSONAPI
```
## A minimal API
Create a test.py file and copy the following code into it
```python
from pathlib import Path
from typing import Any, ClassVar, Dict
import uvicorn
from fastapi import APIRouter, Depends, FastAPI
from sqlalchemy import Column, Integer, Text
from sqlalchemy.engine import make_url
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from fastapi_jsonapi import RoutersJSONAPI, init
from fastapi_jsonapi.misc.sqla.generics.base import DetailViewBaseGeneric, ListViewBaseGeneric
from fastapi_jsonapi.schema_base import BaseModel
from fastapi_jsonapi.views.utils import HTTPMethod, HTTPMethodConfig
from fastapi_jsonapi.views.view_base import ViewBase
CURRENT_FILE = Path(__file__).resolve()
CURRENT_DIR = CURRENT_FILE.parent
DB_URL = f"sqlite+aiosqlite:///{CURRENT_DIR}/db.sqlite3"
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(Text, nullable=True)
class UserAttributesBaseSchema(BaseModel):
name: str
class Config:
"""Pydantic schema config."""
orm_mode = True
class UserSchema(UserAttributesBaseSchema):
"""User base schema."""
class UserPatchSchema(UserAttributesBaseSchema):
"""User PATCH schema."""
class UserInSchema(UserAttributesBaseSchema):
"""User input schema."""
def async_session() -> sessionmaker:
engine = create_async_engine(url=make_url(DB_URL))
_async_session = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False)
return _async_session
class Connector:
@classmethod
async def get_session(cls):
"""
Get session as dependency
:return:
"""
sess = async_session()
async with sess() as db_session: # type: AsyncSession
yield db_session
await db_session.rollback()
async def sqlalchemy_init() -> None:
engine = create_async_engine(url=make_url(DB_URL))
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
class SessionDependency(BaseModel):
session: AsyncSession = Depends(Connector.get_session)
class Config:
arbitrary_types_allowed = True
def session_dependency_handler(view: ViewBase, dto: SessionDependency) -> Dict[str, Any]:
return {
"session": dto.session,
}
class UserDetailView(DetailViewBaseGeneric):
method_dependencies: ClassVar[Dict[HTTPMethod, HTTPMethodConfig]] = {
HTTPMethod.ALL: HTTPMethodConfig(
dependencies=SessionDependency,
prepare_data_layer_kwargs=session_dependency_handler,
)
}
class UserListView(ListViewBaseGeneric):
method_dependencies: ClassVar[Dict[HTTPMethod, HTTPMethodConfig]] = {
HTTPMethod.ALL: HTTPMethodConfig(
dependencies=SessionDependency,
prepare_data_layer_kwargs=session_dependency_handler,
)
}
def add_routes(app: FastAPI):
tags = [
{
"name": "User",
"description": "",
},
]
router: APIRouter = APIRouter()
RoutersJSONAPI(
router=router,
path="/users",
tags=["User"],
class_detail=UserDetailView,
class_list=UserListView,
schema=UserSchema,
resource_type="user",
schema_in_patch=UserPatchSchema,
schema_in_post=UserInSchema,
model=User,
)
app.include_router(router, prefix="")
return tags
def create_app() -> FastAPI:
"""
Create app factory.
:return: app
"""
app = FastAPI(
title="FastAPI and SQLAlchemy",
debug=True,
openapi_url="/openapi.json",
docs_url="/docs",
)
add_routes(app)
app.on_event("startup")(sqlalchemy_init)
init(app)
return app
app = create_app()
if __name__ == "__main__":
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8080,
reload=True,
app_dir=str(CURRENT_DIR),
)
```
This example provides the following API structure:
| URL | method | endpoint | Usage |
|-------------------|--------|-------------|---------------------------|
| `/users` | GET | user_list | Get a collection of users |
| `/users` | POST | user_list | Create a user |
| `/users` | DELETE | user_list | Delete users |
| `/users/{obj_id}` | GET | user_detail | Get user details |
| `/users/{obj_id}` | PATCH | user_detail | Update a user |
| `/users/{obj_id}` | DELETE | user_detail | Delete a user |
Raw data
{
"_id": null,
"home_page": null,
"name": "FastAPI-JSONAPI",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "fastapi, json:api, jsonapi",
"author": null,
"author_email": "Aleksey Nekrasov <a.nekrasov@mts.ai>, Suren Khorenyan <s.khorenyan@mts.ai>, German Bernadskiy <german11235813@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/7c/e3/d9f1a13b79d2871afa330d54ee33572278328e5dd95e8fadcf2ee5793e5d/fastapi_jsonapi-2.8.0.tar.gz",
"platform": null,
"description": "[![Last Commit](https://img.shields.io/github/last-commit/mts-ai/FastAPI-JSONAPI?style=for-the-badge)](https://github.com/mts-ai/FastAPI-JSONAPI)\n[![PyPI](https://img.shields.io/pypi/v/fastapi-jsonapi?label=PyPI&style=for-the-badge)](https://pypi.org/project/FastAPI-JSONAPI/)\n[![](https://img.shields.io/pypi/pyversions/FastAPI-JSONAPI?style=for-the-badge)](https://pypi.org/project/FastAPI-JSONAPI/)\n[![](https://img.shields.io/github/license/ycd/manage-fastapi?style=for-the-badge)](https://pypi.org/project/FastAPI-JSONAPI/)\n[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/mts-ai/FastAPI-JSONAPI/testing.yml?style=for-the-badge)](https://github.com/mts-ai/FastAPI-JSONAPI/actions)\n[![Read the Docs](https://img.shields.io/readthedocs/fastapi-jsonapi?style=for-the-badge)](https://fastapi-jsonapi.readthedocs.io/en/latest/)\n[![Codecov](https://img.shields.io/codecov/c/github/mts-ai/FastAPI-JSONAPI?style=for-the-badge)](https://codecov.io/gh/mts-ai/FastAPI-JSONAPI)\n\n[![\ud83d\udcd6 Docs (gh-pages)](https://github.com/mts-ai/FastAPI-JSONAPI/actions/workflows/documentation.yaml/badge.svg)](https://mts-ai.github.io/FastAPI-JSONAPI/)\n\n# FastAPI-JSONAPI\n\nFastAPI-JSONAPI is a FastAPI extension for building REST APIs.\nImplementation of a strong specification [JSONAPI 1.0](http://jsonapi.org/).\nThis framework is designed to quickly build REST APIs and fit the complexity\nof real life projects with legacy data and multiple data storages.\n\n## Architecture\n\n![docs/img/schema.png](docs/img/schema.png)\n\n## Install\n\n```bash\npip install FastAPI-JSONAPI\n```\n\n## A minimal API\n\nCreate a test.py file and copy the following code into it\n\n```python\nfrom pathlib import Path\nfrom typing import Any, ClassVar, Dict\n\nimport uvicorn\nfrom fastapi import APIRouter, Depends, FastAPI\nfrom sqlalchemy import Column, Integer, Text\nfrom sqlalchemy.engine import make_url\nfrom sqlalchemy.ext.asyncio import AsyncSession, create_async_engine\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy.orm import sessionmaker\n\nfrom fastapi_jsonapi import RoutersJSONAPI, init\nfrom fastapi_jsonapi.misc.sqla.generics.base import DetailViewBaseGeneric, ListViewBaseGeneric\nfrom fastapi_jsonapi.schema_base import BaseModel\nfrom fastapi_jsonapi.views.utils import HTTPMethod, HTTPMethodConfig\nfrom fastapi_jsonapi.views.view_base import ViewBase\n\nCURRENT_FILE = Path(__file__).resolve()\nCURRENT_DIR = CURRENT_FILE.parent\nDB_URL = f\"sqlite+aiosqlite:///{CURRENT_DIR}/db.sqlite3\"\n\nBase = declarative_base()\n\n\nclass User(Base):\n __tablename__ = \"users\"\n id = Column(Integer, primary_key=True, autoincrement=True)\n name = Column(Text, nullable=True)\n\n\nclass UserAttributesBaseSchema(BaseModel):\n name: str\n\n class Config:\n \"\"\"Pydantic schema config.\"\"\"\n\n orm_mode = True\n\n\nclass UserSchema(UserAttributesBaseSchema):\n \"\"\"User base schema.\"\"\"\n\n\nclass UserPatchSchema(UserAttributesBaseSchema):\n \"\"\"User PATCH schema.\"\"\"\n\n\nclass UserInSchema(UserAttributesBaseSchema):\n \"\"\"User input schema.\"\"\"\n\n\ndef async_session() -> sessionmaker:\n engine = create_async_engine(url=make_url(DB_URL))\n _async_session = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False)\n return _async_session\n\n\nclass Connector:\n @classmethod\n async def get_session(cls):\n \"\"\"\n Get session as dependency\n\n :return:\n \"\"\"\n sess = async_session()\n async with sess() as db_session: # type: AsyncSession\n yield db_session\n await db_session.rollback()\n\n\nasync def sqlalchemy_init() -> None:\n engine = create_async_engine(url=make_url(DB_URL))\n async with engine.begin() as conn:\n await conn.run_sync(Base.metadata.create_all)\n\n\nclass SessionDependency(BaseModel):\n session: AsyncSession = Depends(Connector.get_session)\n\n class Config:\n arbitrary_types_allowed = True\n\n\ndef session_dependency_handler(view: ViewBase, dto: SessionDependency) -> Dict[str, Any]:\n return {\n \"session\": dto.session,\n }\n\n\nclass UserDetailView(DetailViewBaseGeneric):\n method_dependencies: ClassVar[Dict[HTTPMethod, HTTPMethodConfig]] = {\n HTTPMethod.ALL: HTTPMethodConfig(\n dependencies=SessionDependency,\n prepare_data_layer_kwargs=session_dependency_handler,\n )\n }\n\n\nclass UserListView(ListViewBaseGeneric):\n method_dependencies: ClassVar[Dict[HTTPMethod, HTTPMethodConfig]] = {\n HTTPMethod.ALL: HTTPMethodConfig(\n dependencies=SessionDependency,\n prepare_data_layer_kwargs=session_dependency_handler,\n )\n }\n\n\ndef add_routes(app: FastAPI):\n tags = [\n {\n \"name\": \"User\",\n \"description\": \"\",\n },\n ]\n\n router: APIRouter = APIRouter()\n RoutersJSONAPI(\n router=router,\n path=\"/users\",\n tags=[\"User\"],\n class_detail=UserDetailView,\n class_list=UserListView,\n schema=UserSchema,\n resource_type=\"user\",\n schema_in_patch=UserPatchSchema,\n schema_in_post=UserInSchema,\n model=User,\n )\n\n app.include_router(router, prefix=\"\")\n return tags\n\n\ndef create_app() -> FastAPI:\n \"\"\"\n Create app factory.\n\n :return: app\n \"\"\"\n app = FastAPI(\n title=\"FastAPI and SQLAlchemy\",\n debug=True,\n openapi_url=\"/openapi.json\",\n docs_url=\"/docs\",\n )\n add_routes(app)\n app.on_event(\"startup\")(sqlalchemy_init)\n init(app)\n return app\n\n\napp = create_app()\n\nif __name__ == \"__main__\":\n uvicorn.run(\n \"main:app\",\n host=\"0.0.0.0\",\n port=8080,\n reload=True,\n app_dir=str(CURRENT_DIR),\n )\n```\n\nThis example provides the following API structure:\n\n| URL | method | endpoint | Usage |\n|-------------------|--------|-------------|---------------------------|\n| `/users` | GET | user_list | Get a collection of users |\n| `/users` | POST | user_list | Create a user |\n| `/users` | DELETE | user_list | Delete users |\n| `/users/{obj_id}` | GET | user_detail | Get user details |\n| `/users/{obj_id}` | PATCH | user_detail | Update a user |\n| `/users/{obj_id}` | DELETE | user_detail | Delete a user |\n",
"bugtrack_url": null,
"license": null,
"summary": "FastAPI extension to create REST web api according to JSON:API 1.0 specification with FastAPI, Pydantic and data provider of your choice (SQLAlchemy, Tortoise ORM)",
"version": "2.8.0",
"project_urls": {
"Documentation": "https://fastapi-jsonapi.readthedocs.io/",
"Source": "https://github.com/mts-ai/FastAPI-JSONAPI"
},
"split_keywords": [
"fastapi",
" json:api",
" jsonapi"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "7a6c1c1a7142b69662b802e511c4318d931adbf539827511f62cdb0fc8f7e609",
"md5": "ea365c206ab738b01a5c6e06202e3396",
"sha256": "a8adc94045fe1742577347e32d4fa0352941ce728b6a65b4483a3e2b99190583"
},
"downloads": -1,
"filename": "fastapi_jsonapi-2.8.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "ea365c206ab738b01a5c6e06202e3396",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 69777,
"upload_time": "2024-04-27T13:27:08",
"upload_time_iso_8601": "2024-04-27T13:27:08.649160Z",
"url": "https://files.pythonhosted.org/packages/7a/6c/1c1a7142b69662b802e511c4318d931adbf539827511f62cdb0fc8f7e609/fastapi_jsonapi-2.8.0-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7ce3d9f1a13b79d2871afa330d54ee33572278328e5dd95e8fadcf2ee5793e5d",
"md5": "d60191d46cb6c269ae1d7a9c2ead3a6e",
"sha256": "06883e2d846635a1e6149d9307cd4ff397f8169a5ba6978020fbc89a4f6929e4"
},
"downloads": -1,
"filename": "fastapi_jsonapi-2.8.0.tar.gz",
"has_sig": false,
"md5_digest": "d60191d46cb6c269ae1d7a9c2ead3a6e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 66759,
"upload_time": "2024-04-27T13:27:10",
"upload_time_iso_8601": "2024-04-27T13:27:10.240956Z",
"url": "https://files.pythonhosted.org/packages/7c/e3/d9f1a13b79d2871afa330d54ee33572278328e5dd95e8fadcf2ee5793e5d/fastapi_jsonapi-2.8.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-27 13:27:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mts-ai",
"github_project": "FastAPI-JSONAPI",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "fastapi-jsonapi"
}