1212
1313
1414@dataclass
15- class ParameterDefinition :
15+ class Parameter :
1616 param_name : str
1717 field_name : str
18+ view_name : str
1819 lookup : str
1920 negate : bool
2021 filter : 'Filter'
@@ -35,6 +36,7 @@ def __init__(
3536 default : Any = None ,
3637 default_lookup : Optional [str ] = None ,
3738 description : Optional [str ] = None ,
39+ method : Optional [str ] = None ,
3840 _field_attrs : Optional [Dict [str , Any ]] = None ,
3941 _field_type : Optional [Type ] = None ,
4042 ** kwargs ,
@@ -49,6 +51,7 @@ def __init__(
4951 self .lookups = lookups or [self .default_lookup or 'exact' ]
5052 self .required = required
5153 self .exclude = exclude
54+ self .method = method
5255 self .field_attrs = {
5356 'description' : description ,
5457 'default' : default or ... if (self .required and len (self .lookups ) == 1 ) else None ,
@@ -76,17 +79,18 @@ def _validate(self):
7679 if token not in self .lookups :
7780 raise ValueError (f"default_lookup '{ self .default_lookup } ' not in lookups { self .lookups } " )
7881
79- def get_param_definitions (self ) -> List [ParameterDefinition ]:
80- defs : List [ParameterDefinition ] = []
82+ def get_param_definitions (self ) -> List [Parameter ]:
83+ defs : List [Parameter ] = []
8184 for lookup in self .lookups :
8285 display_token = f'not_{ lookup } ' if self .exclude else lookup
8386 annotation = LOOKUP_TYPES .get (lookup , self .field_type )
8487 param_name , negate_flag = self ._resolve_param_name (lookup , display_token )
85- param_def = ParameterDefinition (
88+ param_def = Parameter (
8689 param_name = param_name ,
8790 negate = negate_flag ,
8891 annotation = Optional [annotation ], # type:ignore
8992 filter = self ,
93+ view_name = self .view_name ,
9094 field_attrs = self .field_attrs ,
9195 field_name = self .field_name ,
9296 lookup = lookup ,
@@ -153,7 +157,7 @@ def __new__(mcs, name, bases, namespace, **kwargs):
153157 if not isinstance (filters , list ):
154158 raise ValueError ('fields must be a list of Filter objects' )
155159
156- param_map : Dict [str , ParameterDefinition ] = {}
160+ param_map : Dict [str , Parameter ] = {}
157161 for f in filters :
158162 if not isinstance (f , Filter ):
159163 raise ValueError ('All elements of fields must be Filter instances' )
@@ -181,7 +185,7 @@ def _validate_model(self):
181185
182186 @classmethod
183187 def get_build (cls ):
184- param_map : Dict [str , ParameterDefinition ] = getattr (cls , '_param_map' , {})
188+ param_map : Dict [str , Parameter ] = getattr (cls , '_param_map' , {})
185189
186190 def build (** kwargs ):
187191 data = {k : v for k , v in kwargs .items () if v is not None }
@@ -201,19 +205,30 @@ def build(**kwargs):
201205 return build
202206
203207 def filter_queryset (self , queryset : QuerySet ) -> QuerySet :
204- param_map : Dict [str , ParameterDefinition ] = getattr (self , '_param_map' , {})
208+ param_map : Dict [str , Parameter ] = getattr (self , '_param_map' , {})
205209
206210 for pname , raw_value in self .data .items ():
207- info : Optional [ParameterDefinition ] = param_map .get (pname )
208- if not info or raw_value is None :
211+ parameter : Optional [Parameter ] = param_map .get (pname )
212+ if not parameter or raw_value is None :
209213 continue
210214
211- processed = info .filter ._process_value (raw_value , info .lookup )
215+ processed = parameter .filter ._process_value (raw_value , parameter .lookup )
212216 if processed is None :
213217 continue
214218
215- kwargs = LOOKUP_EXPRESSIONS [info .lookup ](info .field_name , processed )
216- queryset = queryset .exclude (** kwargs ) if info .negate else queryset .filter (** kwargs )
219+ if parameter .filter .method :
220+ method = getattr (self , parameter .filter .method , None )
221+ if method and callable (method ):
222+ result = method (queryset = queryset , value = processed , parameter = parameter )
223+ if isinstance (result , QuerySet ):
224+ queryset = result
225+ else :
226+ queryset = self .filter_by_parameter (queryset , processed , parameter )
227+ return queryset
228+
229+ def filter_by_parameter (self , queryset : QuerySet , value : Any , parameter : Parameter ) -> QuerySet :
230+ kwargs = LOOKUP_EXPRESSIONS [parameter .lookup ](parameter .field_name , value )
231+ queryset = queryset .exclude (** kwargs ) if parameter .negate else queryset .filter (** kwargs )
217232 return queryset
218233
219234
0 commit comments