1111from collections .abc import AsyncGenerator , Callable , Generator
1212from typing import (
1313 TYPE_CHECKING ,
14+ Annotated ,
1415 Any ,
1516 Literal ,
1617 NamedTuple ,
2425from uuid import UUID
2526
2627from litestar .di import Provide
27- from litestar .params import Dependency , Parameter
28+ from litestar .params import Dependency , FromQuery , QueryParameter
2829from typing_extensions import NotRequired
2930
3031from advanced_alchemy .filters import (
@@ -407,7 +408,7 @@ def _create_statement_filters( # noqa: C901
407408 if config .get ("id_filter" , False ):
408409
409410 def provide_id_filter ( # pyright: ignore[reportUnknownParameterType]
410- ids : Optional [list [str ]] = Parameter ( query = "ids" , default = None , required = False ) ,
411+ ids : FromQuery [ Optional [list [str ]]] = None ,
411412 ) -> CollectionFilter : # pyright: ignore[reportMissingTypeArgument]
412413 return CollectionFilter (field_name = config .get ("id_field" , "id" ), values = ids )
413414
@@ -416,8 +417,8 @@ def provide_id_filter( # pyright: ignore[reportUnknownParameterType]
416417 if config .get ("created_at" , False ):
417418
418419 def provide_created_filter (
419- before : DTorNone = Parameter ( query = "createdBefore" , default = None , required = False ) ,
420- after : DTorNone = Parameter ( query = "createdAfter" , default = None , required = False ) ,
420+ before : Annotated [ DTorNone , QueryParameter ( name = "createdBefore" )] = None ,
421+ after : Annotated [ DTorNone , QueryParameter ( name = "createdAfter" )] = None ,
421422 ) -> BeforeAfter :
422423 return BeforeAfter ("created_at" , before , after )
423424
@@ -426,8 +427,8 @@ def provide_created_filter(
426427 if config .get ("updated_at" , False ):
427428
428429 def provide_updated_filter (
429- before : DTorNone = Parameter ( query = "updatedBefore" , default = None , required = False ) ,
430- after : DTorNone = Parameter ( query = "updatedAfter" , default = None , required = False ) ,
430+ before : Annotated [ DTorNone , QueryParameter ( name = "updatedBefore" )] = None ,
431+ after : Annotated [ DTorNone , QueryParameter ( name = "updatedAfter" )] = None ,
431432 ) -> BeforeAfter :
432433 return BeforeAfter ("updated_at" , before , after )
433434
@@ -436,13 +437,14 @@ def provide_updated_filter(
436437 if config .get ("pagination_type" ) == "limit_offset" :
437438
438439 def provide_limit_offset_pagination (
439- current_page : int = Parameter (ge = 1 , query = "currentPage" , default = 1 , required = False ),
440- page_size : int = Parameter (
441- query = "pageSize" ,
442- ge = 1 ,
443- default = config .get ("pagination_size" , dep_defaults .DEFAULT_PAGINATION_SIZE ),
444- required = False ,
445- ),
440+ current_page : Annotated [int , QueryParameter (ge = 1 , name = "currentPage" )] = 1 ,
441+ page_size : Annotated [
442+ int ,
443+ QueryParameter (
444+ name = "pageSize" ,
445+ ge = 1 ,
446+ ),
447+ ] = config .get ("pagination_size" , dep_defaults .DEFAULT_PAGINATION_SIZE ),
446448 ) -> LimitOffset :
447449 return LimitOffset (page_size , page_size * (current_page - 1 ))
448450
@@ -453,18 +455,20 @@ def provide_limit_offset_pagination(
453455 if search_fields := config .get ("search" ):
454456
455457 def provide_search_filter (
456- search_string : StringOrNone = Parameter (
457- title = "Field to search" ,
458- query = "searchString" ,
459- default = None ,
460- required = False ,
461- ),
462- ignore_case : BooleanOrNone = Parameter (
463- title = "Search should be case sensitive" ,
464- query = "searchIgnoreCase" ,
465- default = config .get ("search_ignore_case" , False ),
466- required = False ,
467- ),
458+ search_string : Annotated [
459+ StringOrNone ,
460+ QueryParameter (
461+ name = "searchString" ,
462+ title = "Field to search" ,
463+ ),
464+ ] = None ,
465+ ignore_case : Annotated [
466+ BooleanOrNone ,
467+ QueryParameter (
468+ name = "searchIgnoreCase" ,
469+ title = "Search should be case sensitive" ,
470+ ),
471+ ] = config .get ("search_ignore_case" , False ),
468472 ) -> SearchFilter :
469473 # Handle both string and set input types for search fields
470474 field_names = set (search_fields .split ("," )) if isinstance (search_fields , str ) else set (search_fields )
@@ -480,18 +484,20 @@ def provide_search_filter(
480484 if sort_field := config .get ("sort_field" ):
481485
482486 def provide_order_by (
483- field_name : StringOrNone = Parameter (
484- title = "Order by field" ,
485- query = "orderBy" ,
486- default = sort_field ,
487- required = False ,
488- ),
489- sort_order : SortOrderOrNone = Parameter (
490- title = "Field to search" ,
491- query = "sortOrder" ,
492- default = config .get ("sort_order" , "desc" ),
493- required = False ,
494- ),
487+ field_name : Annotated [
488+ StringOrNone ,
489+ QueryParameter (
490+ title = "Order by field" ,
491+ name = "orderBy" ,
492+ ),
493+ ] = sort_field ,
494+ sort_order : Annotated [
495+ SortOrderOrNone ,
496+ QueryParameter (
497+ title = "Field to search" ,
498+ name = "sortOrder" ,
499+ ),
500+ ] = config .get ("sort_order" , "desc" ),
495501 ) -> OrderBy :
496502 return OrderBy (field_name = field_name , sort_order = sort_order ) # type: ignore[arg-type]
497503
@@ -522,24 +528,24 @@ def provide_not_in_filter( # pyright: ignore
522528 else None
523529 )
524530
531+ annotation = Annotated [
532+ Optional [list [field_name .type_hint ]], # type: ignore
533+ QueryParameter (name = camelize (param_name )),
534+ ]
525535 provide_not_in_filter .__name__ = f"provide_not_in_filter_{ field_name .name } "
526536 provide_not_in_filter .__signature__ = inspect .Signature ( # type: ignore[attr-defined]
527537 parameters = [
528538 inspect .Parameter (
529539 name = param_name ,
530540 kind = inspect .Parameter .POSITIONAL_OR_KEYWORD ,
531- default = Parameter (
532- query = camelize (param_name ),
533- default = None ,
534- required = False ,
535- ),
536- annotation = Optional [list [field_name .type_hint ]], # type: ignore
541+ default = None ,
542+ annotation = annotation ,
537543 )
538544 ],
539545 return_annotation = Optional [NotInCollectionFilter [field_name .type_hint ]], # type: ignore
540546 )
541547 provide_not_in_filter .__annotations__ = {
542- param_name : Optional [ list [ field_name . type_hint ]], # type: ignore
548+ param_name : annotation ,
543549 "return" : Optional [NotInCollectionFilter [field_name .type_hint ]], # type: ignore
544550 }
545551 return provide_not_in_filter # pyright: ignore
@@ -573,23 +579,25 @@ def provide_in_filter( # pyright: ignore
573579 )
574580
575581 provide_in_filter .__name__ = f"provide_in_filter_{ field_name .name } "
582+ annotation = Annotated [
583+ Optional [list [field_name .type_hint ]], # type: ignore
584+ QueryParameter (
585+ name = camelize (param_name ),
586+ ),
587+ ]
576588 provide_in_filter .__signature__ = inspect .Signature ( # type: ignore[attr-defined]
577589 parameters = [
578590 inspect .Parameter (
579591 name = param_name ,
580592 kind = inspect .Parameter .POSITIONAL_OR_KEYWORD ,
581- default = Parameter (
582- query = camelize (param_name ),
583- default = None ,
584- required = False ,
585- ),
586- annotation = Optional [list [field_name .type_hint ]], # type: ignore
593+ default = None ,
594+ annotation = annotation ,
587595 )
588596 ],
589597 return_annotation = Optional [CollectionFilter [field_name .type_hint ]], # type: ignore
590598 )
591599 provide_in_filter .__annotations__ = {
592- param_name : Optional [ list [ field_name . type_hint ]], # type: ignore
600+ param_name : annotation ,
593601 "return" : Optional [CollectionFilter [field_name .type_hint ]], # type: ignore
594602 }
595603 return provide_in_filter # pyright: ignore
0 commit comments