1717class FilterSetMetaclass (filterset .FilterSetMetaclass ):
1818 def __new__ (cls , name , bases , attrs ):
1919 new_class = super (FilterSetMetaclass , cls ).__new__ (cls , name , bases , attrs )
20+
2021 opts = copy .deepcopy (new_class ._meta )
22+ orig_meta = new_class ._meta
23+
24+ declared_filters = new_class .declared_filters .copy ()
25+ orig_declared = new_class .declared_filters
2126
22- # If no model is defined, skip all lookups processing
27+ # If no model is defined, skip auto filter processing
2328 if not opts .model :
2429 return new_class
2530
26- # Determine declared filters and filters to generate lookups from. Declared
27- # filters have precedence over generated filters and should not be overwritten.
28- declared_filters , lookups_filters = OrderedDict (), OrderedDict ()
29- for name , f in six .iteritems (new_class .declared_filters ):
30- if isinstance (f , (filters .AllLookupsFilter , filters .RelatedFilter )):
31- lookups_filters [name ] = f
31+ # Generate filters for auto filters
32+ auto_filters = OrderedDict ([
33+ (param , f ) for param , f in six .iteritems (new_class .declared_filters )
34+ if isinstance (f , filters .AutoFilter )
35+ ])
3236
33- # `AllLookupsFilter` is an exception, as it should be overwritten
34- if not isinstance (f , filters .AllLookupsFilter ):
35- declared_filters [name ] = f
37+ # Remove auto filters from declared_filters so that they *are* overwritten
38+ # RelatedFilter is an exception, and should *not* be overwritten
39+ for param , f in six .iteritems (auto_filters ):
40+ if not isinstance (f , filters .RelatedFilter ):
41+ del declared_filters [param ]
3642
37- # generate filters for AllLookups/Related filters
38- # name is the parameter name on the filterset, f.name is the model field's name
39- for name , f in six .iteritems (lookups_filters ):
43+ for param , f in six .iteritems (auto_filters ):
4044 opts .fields = {f .name : f .lookups or []}
41- new_filters = new_class .filters_for_model (opts .model , opts )
4245
43- # filters_for_model generate param names from the model field name
44- # replace model field name with the parameter name from the filerset
46+ # patch, generate auto filters
47+ new_class ._meta , new_class .declared_filters = opts , declared_filters
48+ generated_filters = new_class .get_filters ()
49+
50+ # get_filters() generates param names from the model field name
51+ # Replace the field name with the parameter name from the filerset
4552 new_class .base_filters .update (OrderedDict (
46- (param .replace (f .name , name , 1 ), v )
47- for param , v in six .iteritems (new_filters )
53+ (gen_param .replace (f .name , param , 1 ), gen_f )
54+ for gen_param , gen_f in six .iteritems (generated_filters )
4855 ))
4956
50- # re-apply declared filters (sans `AllLookupsFilter`s)
51- new_class . base_filters . update ( declared_filters )
57+ new_class . _meta , new_class . declared_filters = orig_meta , orig_declared
58+
5259 return new_class
5360
5461 @property
@@ -68,26 +75,17 @@ class FilterSet(six.with_metaclass(FilterSetMetaclass, rest_framework.FilterSet)
6875 _subset_cache = {}
6976
7077 @classmethod
71- def filters_for_model (cls , model , opts ):
72- fields = opts .fields
73-
74- if not isinstance (fields , dict ):
75- return super (FilterSet , cls ).filters_for_model (model , opts )
78+ def get_fields (cls ):
79+ fields = super (FilterSet , cls ).get_fields ()
7680
77- # replace all '__all__' values by the resolved list of all lookups
78- fields = fields .copy ()
7981 for name , lookups in six .iteritems (fields ):
8082 if lookups == filters .ALL_LOOKUPS :
81- field = get_model_field (model , name )
83+ field = get_model_field (cls . _meta . model , name )
8284 fields [name ] = utils .lookups_for_field (field )
8385
84- return filterset .filters_for_model (
85- model , fields , opts .exclude ,
86- cls .filter_for_field ,
87- cls .filter_for_reverse_field
88- )
86+ return fields
8987
90- def get_filters (self ):
88+ def expand_filters (self ):
9189 """
9290 Build a set of filters based on the requested data. The resulting set
9391 will walk `RelatedFilter`s to recursively build the set of filters.
@@ -128,7 +126,7 @@ def get_filters(self):
128126 filterset = subset_class (data = subset_data )
129127
130128 # modify filter names to account for relationship
131- for related_name , related_f in six .iteritems (filterset .get_filters ()):
129+ for related_name , related_f in six .iteritems (filterset .expand_filters ()):
132130 related_name = LOOKUP_SEP .join ([filter_name , related_name ])
133131 related_f .name = LOOKUP_SEP .join ([f .name , related_f .name ])
134132 requested_filters [related_name ] = related_f
@@ -258,7 +256,7 @@ def cache_set(cls, key, value):
258256 @property
259257 def qs (self ):
260258 available_filters = self .filters
261- requested_filters = self .get_filters ()
259+ requested_filters = self .expand_filters ()
262260
263261 self .filters = requested_filters
264262 qs = super (FilterSet , self ).qs
0 commit comments