Example #1
0
 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
Example #2
0
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)
Example #3
0
 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'])