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)
Project description
FastAPI-JSONAPI
FastAPI-JSONAPI is a FastAPI extension for building REST APIs. Implementation of a strong specification JSONAPI 1.0. 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
Install
pip install FastAPI-JSONAPI
A minimal API
Create a test.py file and copy the following code into it
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 |
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
File details
Details for the file fastapi_jsonapi-2.8.0.tar.gz
.
File metadata
- Download URL: fastapi_jsonapi-2.8.0.tar.gz
- Upload date:
- Size: 66.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.11.9
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 06883e2d846635a1e6149d9307cd4ff397f8169a5ba6978020fbc89a4f6929e4 |
|
MD5 | d60191d46cb6c269ae1d7a9c2ead3a6e |
|
BLAKE2b-256 | 7ce3d9f1a13b79d2871afa330d54ee33572278328e5dd95e8fadcf2ee5793e5d |
File details
Details for the file fastapi_jsonapi-2.8.0-py2.py3-none-any.whl
.
File metadata
- Download URL: fastapi_jsonapi-2.8.0-py2.py3-none-any.whl
- Upload date:
- Size: 69.8 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.11.9
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | a8adc94045fe1742577347e32d4fa0352941ce728b6a65b4483a3e2b99190583 |
|
MD5 | ea365c206ab738b01a5c6e06202e3396 |
|
BLAKE2b-256 | 7a6c1c1a7142b69662b802e511c4318d931adbf539827511f62cdb0fc8f7e609 |