awtkns / fastapi-crudrouter

A dynamic FastAPI router that automatically creates CRUD routes for your models
https://fastapi-crudrouter.awtkns.com
MIT License
1.37k stars 155 forks source link

Question: How to add function to route #136

Open sobeasy opened 2 years ago

sobeasy commented 2 years ago

Following the Overriding Example, we can easily override the default router:

from pydantic import BaseModel
from fastapi import FastAPI
from fastapi_crudrouter import MemoryCRUDRouter as CRUDRouter

class Potato(BaseModel):
    id: int
    color: str
    mass: float

app = FastAPI()
router = CRUDRouter(schema=Potato)

@router.get('')
def overloaded_get_all():
    return 'My overloaded route that returns all the items'

@router.get('/{item_id}')
def overloaded_get_one():
    return 'My overloaded route that returns one item'

app.include_router(router)

However, I would like to use the default put router (to update) but also add function to that router (e.g. notify user / write a log etc.) , may i know if any hints to do so ?

from pydantic import BaseModel
from fastapi import FastAPI
from fastapi_crudrouter import MemoryCRUDRouter as CRUDRouter

class Potato(BaseModel):
    id: int
    color: str
    mass: float

app = FastAPI()
router = CRUDRouter(schema=Potato)

@router.put('/{item_id}')
def update_the_row(item_id, row: Rows):
    # do the default router
    # do what we wanna do

app.include_router(router)
satodaiki commented 2 years ago

I don't think there is any official support for this.

I have worked around this in the following way. However, this is definitely not the best solution to this problem. (In the example, I used an override of get_all.)

from typing import List, Optional

import uvicorn
from fastapi import FastAPI
from fastapi_crudrouter import MemoryCRUDRouter as CRUDRouter
from pydantic import BaseModel

class Potato(BaseModel):
    id: int
    color: str
    mass: float

app = FastAPI()
router = CRUDRouter(
    schema=Potato,
    get_all_route=True,
    get_one_route=False,
    create_route=True,
    update_route=False,
    delete_one_route=False,
    delete_all_route=False,
)

for route in router.routes:
    if 'GET' in route.methods and route.path == '/potato':
        get_all_callback = route.endpoint

# Delete the existing APIRoute.
router.get("")

def override_get_all(pagination = router.pagination):
    print("override")
    return get_all_callback(pagination)

router._add_api_route(
    "",
    override_get_all,
    methods=["GET"],
    response_model=Optional[List[router.schema]],
    summary="Get All",
    dependencies=True,
)

app.include_router(router)

if __name__ == '__main__':
    uvicorn.run(app, port=9999)

For overriding, I think we need a formal implementation that can wrap the existing implementation.

ChuckMoe commented 1 year ago

@sobeasy See issue #130 . If this will be implemented, you could use this.