def get_router(self) -> APIRouter: router = APIRouter() router.get('/{model_id}')(self.read_endpoint) router.get('/')(self.index_endpoint) router.post('/')(self.create_endpoint) router.put('/')(self.update_endpoint) router.delete('/')(self.delete_endpoint) return router
def mount(name: str, router: APIRouter, klass_py, klass_orm, ignored=set()): """ mount mounts common CRUD patterns onto the router :param klass_py: Pydantic Model :param klass_orm: sqlalchemy Model :param ignored: set of names to ignore, only from create, read, update, delete, list """ def create(model_py: klass_py, sess: Session = Depends(create_session)): model_orm = klass_orm( **model_py.dict(exclude_none=True, exclude_unset=True)) sess.add(model_orm) sess.flush([model_orm]) return klass_py.from_orm(model_orm) def get(idx: int, sess: Session = Depends(create_session)): model_orm = sess.query(klass_orm).filter(klass_orm.id == idx).one() return klass_py.from_orm(model_orm) def update(model_py: klass_py, sess: Session = Depends(create_session)): if model_py.id is None: raise HTTPException(400, f"{name} id is not given") model_orm: klass_orm = sess.query(klass_orm).filter( klass_orm.id == model_py.id).one() for f, v in model_py.dict(exclude_none=True, exclude_unset=True).items(): if type(v) is dict: # nested models are usually mapped to foreign key objects continue setattr(model_orm, f, v) sess.add(model_orm) return def delete(idx: int, sess: Session = Depends(create_session)): model_orm = sess.query(klass_orm).filter(klass_orm.id == idx).one() sess.delete(model_orm) return klass_py.from_orm(model_orm) def list_all(sess: Session = Depends(create_session)): return [klass_py.from_orm(u) for u in sess.query(klass_orm).all()] if 'create' not in ignored: router.put('/', response_model=klass_py, status_code=status.HTTP_201_CREATED)(create) if 'read' not in ignored: router.get('/', response_model=klass_py)(get) if 'update' not in ignored: router.post('/')(update) if 'delete' not in ignored: router.delete('/', response_model=klass_py, status_code=status.HTTP_202_ACCEPTED)(delete) if 'list' not in ignored: router.get('/list', response_model=List[klass_py])(list_all)
def register_view(self, view, prefix=None, methods: Union[List[str], Set[str]] = ('GET', 'Retrieve', 'POST', 'PUT', 'DELETE'), tags=None, depends=None): """ 如果不使用自定义的,则需要methods为None :param view: :param prefix: :param methods: :param tags: :return: """ router = APIRouter() if not prefix: prefix = "/" + view.__class__.__name__ if not tags: tags = [prefix[1:]] if not methods: methods = view.methods if methods.count('GET'): # print("注意,可能需要设置返回model") # get_res_model = get_res_schema(view.schema) router.get( prefix, tags=tags, )(view.list) if methods.count('Retrieve'): router.get( prefix + "/{id}", tags=tags, )(view.retrieve) if methods.count('POST'): router.post( prefix, tags=tags, )(view.create) if methods.count('PUT'): router.put( prefix, tags=tags, )(view.update) if methods.count('DELETE'): router.delete(prefix + "/{id}", tags=tags)(view.delete) self.__router.include_router(router, prefix='/admin')
router = APIRouter() user_view = UserView() router.get( "/", name="list", summary="List users", response_model=List[UserEntity], )(user_view.list) router.get( "/{user_id}", name="get", summary="Get user by id", response_model=UserEntity, )(user_view.get) router.post( "/", name="create", summary="Create user", response_model=UserEntity, )(user_view.create) router.delete( "/{user_id}", name="delete", summary="Delete user", response_model=UserEntity, )(user_view.delete)
def create_table_crud(table,app,prefix:str="/db",api_key:str=None): if api_key: os.environ['API_CRUD_KEY']=api_key router = APIRouter() pkey_attr_names = [pkey.name for pkey in table._pk_attrs_] path_args = [f'{{{pk}}}' for pk in pkey_attr_names] get_query_params = [] api_get_params = [] security_parameter = Parameter('_api_key',kind=Parameter.POSITIONAL_OR_KEYWORD,annotation=APIKey,default=Depends(get_api_key)) for col in table._columns_: arg_type = table._adict_.get(col).py_type if arg_type not in [dict,ormtypes.Json]: if arg_type not in [int,bool,float,UUID,datetime]: arg_type=str param = Parameter(col,kind=Parameter.POSITIONAL_OR_KEYWORD,annotation=arg_type,default=None) get_query_params.append(param) if col in pkey_attr_names: api_get_params.append(Parameter(col,kind=Parameter.POSITIONAL_OR_KEYWORD,annotation=arg_type)) if api_key: get_query_params.append(security_parameter) def get_func(*args,**kwargs): return api_get(table,kwargs) sig = signature(get_func) sig = sig.replace(parameters=tuple(get_query_params)) get_func.__signature__ = sig router.get( f"/{table.__name__}", summary=f'get items from {table.__name__} table', response_model= get_api_model(table,"RESPONSE"))(get_func) def del_func(*args,**kwargs): return api_delete(table,kwargs) del_fun_params = api_get_params if api_key: del_fun_params.append(security_parameter) sig = signature(del_func) sig = sig.replace(parameters=tuple(del_fun_params)) del_func.__signature__ = sig router.delete(f"/{table.__name__}/{'/'.join(path_args)}",summary=f'delete items from {table.__name__} table')(del_func) if api_key: @router.post(f"/{table.__name__}",summary=f'post items to {table.__name__} table') def post_func(body:get_api_model(table,"POST"),_api_key:APIKey=Depends(get_api_key)): return api_post(table,body) else: @router.post(f"/{table.__name__}",summary=f'post items to {table.__name__} table') def post_func(body:get_api_model(table,"POST")): return api_post(table,body) def put_func(*args,**kwargs): pkeys = [i.name for i in table._pk_attrs_] entity_pkeys = {i:j for i,j in kwargs.items() if i in pkeys} return api_put(table,new_data = kwargs['body'], entity_pkeys = entity_pkeys) pkey_fun_args = [Parameter(pkey.name,kind=Parameter.POSITIONAL_OR_KEYWORD) for pkey in table._pk_attrs_] body_arg = [Parameter("body",kind=Parameter.POSITIONAL_OR_KEYWORD,annotation=get_api_model(table,"PUT"))] put_args = pkey_fun_args+body_arg if api_key: put_args.append(security_parameter) sig = signature(put_func) sig = sig.replace(parameters=tuple(put_args)) put_func.__signature__ = sig router.put(f"/{table.__name__}/{'/'.join(path_args)}",summary=f'update items in {table.__name__} table')(put_func) app.include_router( router, prefix=prefix, tags=['Database'])