Skip to content

Commit d9e3e91

Browse files
committed
Actions for multiple rows
1 parent d4f635e commit d9e3e91

1 file changed

Lines changed: 54 additions & 33 deletions

File tree

piccolo_api/fastapi/endpoints.py

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
"""
23
Enhancing Piccolo integration with FastAPI.
34
"""
@@ -8,12 +9,13 @@
89
from collections import defaultdict
910
from decimal import Decimal
1011
from enum import Enum
11-
from inspect import Parameter, Signature
12+
from inspect import Parameter, Signature, iscoroutinefunction
1213

1314
from fastapi import APIRouter, FastAPI, Request
1415
from fastapi.params import Query
1516
from pydantic import BaseModel as PydanticBaseModel
1617
from pydantic.main import BaseModel
18+
from pydantic import parse_obj_as
1719
from starlette.responses import JSONResponse
1820

1921
from piccolo_api.crud.endpoints import PiccoloCRUD
@@ -25,6 +27,9 @@ class HTTPMethod(str, Enum):
2527
get = "GET"
2628
delete = "DELETE"
2729

30+
class TableRowDataSchema(PydanticBaseModel):
31+
table_name: str
32+
row_ids: list[str]
2833

2934
class FastAPIKwargs:
3035
"""
@@ -76,12 +81,13 @@ class ReferencesModel(BaseModel):
7681
references: t.List[ReferenceModel]
7782

7883

79-
class CallbackModel(BaseModel):
80-
callback_name: str
84+
class ActionsModel(BaseModel):
85+
action_id: int
86+
action_name: str
8187

8288

83-
class ExecuteCallbackModel(BaseModel):
84-
callback_response: str
89+
class ExecuteActionsModel(BaseModel):
90+
actions_response: str
8591

8692

8793
class FastAPIWrapper:
@@ -103,8 +109,8 @@ class FastAPIWrapper:
103109
and ``allow_bulk_delete``.
104110
:param fastapi_kwargs:
105111
Specifies the extra kwargs to pass to FastAPI's ``add_api_route``.
106-
:param callback
107-
Callback fn passed in via create_admin TableConfig
112+
:param actions
113+
List of action handlers passed in via create_admin TableConfig
108114
109115
"""
110116

@@ -114,15 +120,16 @@ def __init__(
114120
fastapi_app: t.Union[FastAPI, APIRouter],
115121
piccolo_crud: PiccoloCRUD,
116122
fastapi_kwargs: t.Optional[FastAPIKwargs] = None,
117-
callback: t.Optional[t.Callable] = None,
123+
actions: t.Optional[t.List[t.Callable]] = None,
118124
):
119125
fastapi_kwargs = fastapi_kwargs or FastAPIKwargs()
120126

121127
self.root_url = root_url
122128
self.fastapi_app = fastapi_app
123129
self.piccolo_crud = piccolo_crud
124130
self.fastapi_kwargs = fastapi_kwargs
125-
self.callback = callback
131+
self.actions = actions
132+
self._actions_map = []
126133

127134
self.ModelOut = piccolo_crud.pydantic_model_output
128135
self.ModelIn = piccolo_crud.pydantic_model
@@ -257,55 +264,69 @@ async def references(request: Request):
257264
)
258265

259266
#######################################################################
260-
# Root - Callback
267+
# Root - Actions
261268

262-
async def get_callback(request: Request) -> JSONResponse:
269+
async def get_actions(request: Request) -> JSONResponse:
263270
"""
264-
Return the name of the callback function
271+
Return the names of the actions
265272
This is specified on the table config
266273
"""
267-
if self.callback:
268-
return JSONResponse(
269-
f"Configured callback for table: {self.callback.__name__}"
270-
)
274+
if self.actions:
275+
actions_list = []
276+
for action in self._actions_map:
277+
actions_list.append({"action_id": action['action_id'], "action_name": action['action_handler'].__name__})
278+
279+
print(actions_list)
280+
return actions_list
271281
else:
272282
return JSONResponse(
273-
content="No callback configured", status_code=500
283+
content="No actions configured", status_code=500
274284
)
275285

276-
if self.callback:
286+
if self.actions:
287+
for action_id, action in enumerate(actions):
288+
self._actions_map.append({"action_id": action_id, "action_handler": action})
289+
277290
fastapi_app.add_api_route(
278-
path=self.join_urls(root_url, "/callback"),
279-
endpoint=get_callback,
291+
path=self.join_urls(root_url, "/actions"),
292+
endpoint=get_actions,
280293
methods=["GET"],
281-
response_model=CallbackModel,
294+
response_model=t.List[ActionsModel],
282295
**fastapi_kwargs.get_kwargs("get"),
283296
)
284297

285298
#######################################################################
286-
# Root - Callback execute
299+
# Root - Actions execute
287300

288-
async def run_callback(request: Request) -> JSONResponse:
301+
async def run_action(request: Request) -> JSONResponse:
289302
"""
290-
Execute the configured callback for this table
303+
Execute the configured actions for this table
291304
:param request_params:
292305
The request params must contain the arguments
293-
required by the callback
306+
required by the actions handler function
294307
"""
295-
if self.callback:
296-
return await self.callback(request_params=request.json())
308+
action_id = request.path_params.get("action_id", None)
309+
if self._actions_map and action_id:
310+
for action in self._actions_map:
311+
if action['action_id'] == int(action_id):
312+
action_handler = action['action_handler']
313+
req_data = await request.json()
314+
if iscoroutinefunction(action_handler):
315+
return await action_handler(data=parse_obj_as(TableRowDataSchema, req_data))
316+
else:
317+
return action_handler(data=parse_obj_as(TableRowDataSchema, req_data))
297318
else:
298319
return JSONResponse(
299-
content="No callback configured", status_code=500
320+
content="No actions registered", status_code=500
300321
)
301322

302-
if self.callback:
323+
if self.actions:
303324
fastapi_app.add_api_route(
304-
path=self.join_urls(root_url, "/callback/execute"),
305-
endpoint=run_callback,
325+
path=self.join_urls(root_url, "/actions/{action_id:str}/execute"),
326+
endpoint=run_action,
306327
methods=["POST"],
307-
response_model=ExecuteCallbackModel,
308-
**fastapi_kwargs.get_kwargs("post"),
328+
response_model=ExecuteActionsModel,
329+
**fastapi_kwargs.get_kwargs("POST"),
309330
)
310331
#######################################################################
311332
# Root - DELETE

0 commit comments

Comments
 (0)