FastAPI Simple CRUD Generator
Repository
Installation
pip install fastapi-simple-crud
Description
A package to generate CRUD routers and API in a very simple way. Based on SQLAlchemy asynchronous operation and schema.
Changelogs
- v0.0
- First Upload
- v0.1:
- Added
ExtendedRouter - Bugs fix
- v0.1.4 :
- using
disable_crudfor bothSimpleRouter()andExtendedRouter()(previouslydisable_simple_crudanddisable_extended_crudarguments)
- using
- v0.1.5 :
- Auto Generated PydanticModel from both
SimpleRouter()andExtendedRouter()be accessed from their object
- Auto Generated PydanticModel from both
- v0.1.6 :
RouterMap.update_map()can be used to updateExtendedRouter()
- Added
How to use ?
from fastapi import FastAPI
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from fastapi_simple_crud import RouterMap
engine = create_async_engine("sqlite+aiosqlite:///./test.db", echo=True, future=True)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
Base = declarative_base()
async def get_session() -> AsyncSession:
async with async_session() as session:
yield session
class Country(Base):
__tablename__ = "country"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
name = Column(String(100), nullable=False)
class President(Base):
__tablename__ = "president"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
country_id = Column(Integer, ForeignKey("country.id"))
country = relationship("Country")
class People(Base):
__tablename__ = "people"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
age = Column(Integer)
country_id = Column(Integer, ForeignKey("country.id"))
country = relationship("Country")
app = FastAPI()
@app.on_event("startup")
async def startup():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
## ULTRA SIMPLE OH MY GOD!
MyMap = RouterMap.create_router_map_from_base(base=Base)
RouterMap.generate(app, get_session)
Results
- your endpoints
- your pydantic schema
Example 1b : Too few for you? Relax. We have the Extended Version
simply set the extend parameter to True then you got the fully extended version
## ULTRA SIMPLE OH MY GOD!
RouterMap.create_router_map_from_base(Base, base_prefix="/v1", extend=True)
RouterMap.generate(app, get_session)
- your extended endpoints
Using RouterMap superclass
Simple usage
class MyMap(RouterMap):
country = SimpleRouter(Country)
president = SimpleRouter(President)
people = ExtendedRouter(People)
Additional usage
from fastapi_simple_crud import SimpleCRUDGenerator, RouterMap, SimpleRouter, SimpleEndpoint
## ULTRA SIMPLE OH MY GOD!
class MyPresidentPydantic(BaseModel):
name: int
class MyMap(RouterMap):
country = SimpleRouter(Country, prefix="/v1/country")
president = SimpleRouter(President, prefix="/v1/president",
crud_update=None,
crud_create=SimpleEndpoint(pydantic_model=MyPresidentPydantic),
crud_read=SimpleEndpoint("/custom_read"))
RouterMap.generate(app, get_session)
- This example show how to use
RouterMapas a superclass - You could disable the API generation by simply passing between these keyword arguments to
Nonein theSimpleRouterdefinition:crud_createcrud_readcrud_updatecrud_deletedisable_crud(set this toTruethis will forcely disable all API generation)
- Only your defined router mapping inside you router map (in above example is
MyMapclass) will be generated. From the example,Peoplerouter is not exist. SimpleEndpoint()refers to your HTTP method definition (GET/POST/PUT/DELETE) in the API decorator (ex:@router.get(), etc.)
RouterMap with ExtendedRouter()
from fastapi_simple_crud import SimpleCRUDGenerator, RouterMap, ExtendedRouter, SimpleEndpoint
## ULTRA SIMPLE OH MY GOD!
class MyPresidentPydantic(BaseModel):
name: int
class MyMap(RouterMap):
country = ExtendedRouter(Country, prefix="/v1/country")
president = ExtendedRouter(President, prefix="/v1/president",
read_one=None,
read_many=SimpleEndpoint("/custom_read")),
update_one=SimpleEndpoint(pydantic_model=MyPresidentPydantic)
RouterMap.generate(app, get_session)
- You could disable the API generation by simply passing between these keyword arguments to
Nonein theExtendedRouterdefinition:create_onecreate_manyread_oneread_manyupdate_oneupdate_manydelete_onedelete_manydisable_crud(set this toTruethis will forcely disable all API generation)
Add Your Custom API
from fastapi import Depends
from sqlalchemy import select
from fastapi_simple_crud import SimpleCRUDGenerator, RouterMap, SimpleRouter, SimpleEndpoint
## ULTRA SIMPLE OH MY GOD!
class MyPresidentPydantic(BaseModel):
name: int
class MyMap(RouterMap):
country = SimpleRouter(Country, prefix="/v1/country", crud_read=None)
president = SimpleRouter(President, prefix="/v1/president")
@MyMap.country.get("/custom_read")
async def get_country(id: int, session: AsyncSession = Depends(get_session)):
query = select(Country).where(Country.id==id)
data = await session.execute(query)
data = data.scalars().first()
return data
RouterMap.generate(app, get_session)
- You could use your router from the your router map as shown above
Disabling Some Routers
from fastapi_simple_crud import SimpleCRUDGenerator, RouterMap, SimpleRouter, SimpleEndpoint
## ULTRA SIMPLE OH MY GOD!
MyMap = RouterMap.create_router_map_from_base(base=Base)
## you want to remove people from autogeneration
class NewMap(MyMap):
people = SimpleRouter(People, disable_crud=True)
RouterMap.generate(app, get_session)
or inherit from the RouterMap
class NewMap(RouterMap):
people = SimpleRouter(People, disable_crud=True)
or simply update from the RouterMap
people = SimpleRouter(People, disable_crud=True)
RouterMap.update_map(people)
or from the MyMap
MyMap.update_map(people)
Change Router Type
You can override ExtendedRouter with SimpleRouter and vice versa.
class NewMap(RouterMap):
people = SimpleRouter(People)
class NewMap2(RouterMap):
people = ExtendedRouter(People)
Add your custom API from RouterMap.create_router_map_from_base()
from fastapi import Depends
from sqlalchemy import select
from fastapi_simple_crud import SimpleCRUDGenerator, RouterMap, SimpleRouter, SimpleEndpoint
class Country(Base):
__tablename__ = "country"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
name = Column(String(100), nullable=False)
## ULTRA SIMPLE OH MY GOD!
MyMap = RouterMap.create_router_map_from_base(base=Base)
## use your tablename to get the router attribute from the created router map
## RouterMap in default will automatically mapped your router with its tablename
@MyMap.country.get("/custom_read")
async def get_country(id: int, session: AsyncSession = Depends(get_session)):
query = select(Country).where(Country.id==id)
data = await session.execute(query)
data = data.scalars().first()
return data
RouterMap.generate(app, get_session)
- Use your tablename to get the router attribute from the created router map (in above is
MyMap) RouterMapin default will automatically mapped your router with its tablename (in aboveCountrytablename iscountry)
Want to use your generated pydantic?
class MyMap(RouterMap):
country = SimpleRouter(Country)
president = SimpleRouter(President)
people = ExtendedRouter(People)
## here you go
countryCreateOnePydanticModel = MyMap.country.create_one.pydanticModel
Want to generate your own pydantic from SQLAlchemy schema?
for example we have this class
class People(Base):
__tablename__ = "people"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
age = Column(Integer)
country_id = Column(Integer, ForeignKey("country.id"))
country = relationship("Country")
isAlive = Column(Boolean)
then simply put in to with generate_pydantic_model()
from fastapi import Query
from fastapi_simple_crud.dependencies.utils import generate_pydantic_model
myPeoplePydantic = generate_pydantic_model(People, modelName="myPeoplePydantic")
or with some params..
myPeoplePydantic = generate_pydantic_model(
classModel=People,
modelName="myPeoplePydantic",
exclude_attributes=["id"],
include_attributes_default={"isAlive": True},
include_attributes_paramsType={"isAlive": Query},
)
the code above will generate People pydantic model without id attribute
the available params are:
classModel>> your SQLAlchemy Model Schema ClassmodelName>> your pydantic model nameexclude_attributes>> put the attributes you dont want inside your pydanticModel (it will copy all relatied attributes from the SQLAlchemy schema)include_attributes_default>> set your attributes default paramsinclude_attributes_paramsType>> set your attributes default paramsuniform_attributes_default>> override all default value to uniformuniform_attributes_paramsType>> override all params type to uniform
Metadata
Release files for fastapi-simple-crud 0.1.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fastapi-simple-crud-0.1.6.tar.gz | 18.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_simple_crud-0.1.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.6 kB
Release files / fastapi-simple-crud-0.1.6.tar.gz
| Download URL | fastapi-simple-crud-0.1.6.tar.gz |
|---|---|
| Size | 18.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
731468ac56a48727b609b3206df1ebcdf83b4f7f1541bd92364b5a31e7a855c3
|
|
BLAKE2b-256 checksum How to use checksums |
80ced48cd5e212cca73db3b3b23d57e7285b6f92c0c81291455d37d6c9d079f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.22.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10
|
Release files / fastapi_simple_crud-0.1.6-py3-none-any.whl
| Download URL | fastapi_simple_crud-0.1.6-py3-none-any.whl |
|---|---|
| Size | 18.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b85c11fe80f508196894960908d5bcaf08464e2dd388bc6b5164d7fb11ef6ea0
|
|
BLAKE2b-256 checksum How to use checksums |
9346586d9842287a54b65a7ea6721871db130d1dd6428d802295dfbc69e36633
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.22.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10
|