55from litestar .exceptions import HTTPException
66from msgspec import Struct
77from litestar .openapi import ResponseSpec
8+ from enum import StrEnum
9+ import operator
810
911from src .models .base import AppModel
1012from src .controllers .base import AppController
1315 AppReadDTO ,
1416 AppUpdateDTO ,
1517 AppUpdateWithIdDTO ,
18+ AppSearchDTO ,
1619 AppBulkActionResultDTO ,
1720 AppReadAllPaginationDetailsDTO ,
1821 IntID ,
22+ IntPositive ,
1923 IntNonNegative ,
2024 IntMaxLimit ,
2125)
22- from src .responses import ConflictResponse
26+ from src .response_specs import ConflictResponse
27+
28+
29+ class JoinOperator (StrEnum ):
30+ AND : str = "and"
31+ OR : str = "or"
32+
33+ def operator_mapping (self ):
34+ if self == JoinOperator .AND :
35+ return operator .and_
36+ elif self == JoinOperator .OR :
37+ return operator .or_
2338
2439
2540class CrudController (AppController ): ...
@@ -31,6 +46,7 @@ def generate_crud_controller(
3146 ReadDTO : type [AppReadDTO ],
3247 UpdateDTO : type [AppUpdateDTO ],
3348 UpdateWithIdDTO : type [AppUpdateWithIdDTO ],
49+ SearchDTO : type [AppSearchDTO ],
3450 api_version_prefix : str ,
3551 exclude_from_auth : bool = False ,
3652 read_all_limit_default : int = 100 ,
@@ -62,7 +78,6 @@ def generate_crud_controller(
6278 status_codes .HTTP_409_CONFLICT : ResponseSpec (
6379 data_container = ConflictResponse ,
6480 description = f"Cannot create a { Model .humanise ()} because one with the same primary key already exists." ,
65- examples = ConflictResponse .examples ,
6681 )
6782 },
6883 )
@@ -247,4 +262,26 @@ async def delete_all(
247262 await Model .delete_all (force = True )
248263 setattr (controller_class , "delete_all" , delete_all )
249264
265+
266+ @post (
267+ "/search" ,
268+ description = f"Search for { pluralize (Model .humanise ())} ." ,
269+ exclude_from_auth = exclude_from_auth ,
270+ status_code = status_codes .HTTP_200_OK ,
271+ )
272+ async def search (
273+ self ,
274+ data : SearchDTO , # type: ignore
275+ join_operator : JoinOperator = JoinOperator .AND ,
276+ offset : IntNonNegative = 0 ,
277+ limit : IntMaxLimit = read_all_limit_default ,
278+ ) -> list [ReadDTO ]: # type: ignore
279+ return await Model .search (
280+ data ,
281+ join_operator .operator_mapping (),
282+ offset ,
283+ read_all_limit_default
284+ )
285+ setattr (controller_class , "search" , search )
286+
250287 return controller_class
0 commit comments