Package: fastapi-simple-crud
FastAPI Simple CRUD GeneratorRepositoryGITHUBInstallationpip install fastapi-simple-crudDescriptionA package to generate CRUD routers and API in a very simple way. Based on SQLAlchemy asynchronous operation and schema.Changelogsv0.0First Uploadv0.1:AddedExtendedRouterBugs fixv0.1.4 :usingdisable_crudfor bothSimpleRouter()andExtendedRouter()(previouslydisable_simple_crudanddisable_extended_crudarguments)v0.1.5 :Auto Generated PydanticModel from bothSimpleRouter()andExtendedRouter()be accessed from their objectv0.1.6 :RouterMap.update_map()can be used to updateExtendedRouter()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)Resultsyour endpointsyour pydantic schemaExample 1b : Too few for you? Relax. We have the Extended Versionsimply set theextendparameter toTruethen 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 endpointsUsingRouterMapsuperclassSimple usageclass MyMap(RouterMap):
    country = SimpleRouter(Country)
    president = SimpleRouter(President)
    people = ExtendedRouter(People)Additional usagefrom 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 useRouterMapas a superclassYou could disable the API generation by simply passing between these keyword arguments toNonein 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 isMyMapclass) 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.)RouterMapwithExtendedRouter()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 toNonein theExtendedRouterdefinition:create_onecreate_manyread_oneread_manyupdate_oneupdate_manydelete_onedelete_manydisable_crud(set this toTruethis will forcely disable all API generation)Add Your Custom APIfrom 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 aboveDisabling Some Routersfrom 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 theRouterMapclass NewMap(RouterMap):
    people = SimpleRouter(People, disable_crud=True)or simply update from theRouterMappeople = SimpleRouter(People, disable_crud=True)
RouterMap.update_map(people)or from theMyMapMyMap.update_map(people)Change Router TypeYou can overrideExtendedRouterwithSimpleRouterand vice versa.class NewMap(RouterMap):
    people = SimpleRouter(People)

class NewMap2(RouterMap):
    people = ExtendedRouter(People)Add your custom API fromRouterMap.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 isMyMap)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.pydanticModelWant to generate your own pydantic from SQLAlchemy schema?for example we have this classclass 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 withgenerate_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 generatePeoplepydantic model withoutidattributethe 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