@@ -165,7 +165,7 @@ then we can filter like so::
165165 /api/page/?author__username__icontains=john
166166
167167Automatic Filter Negation/Exclusion
168- ~~~~~~~~~~~~~~~~~~~~~~~~~
168+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169169
170170FilterSets also support automatic exclusion using a simple ``k!=v `` syntax. This syntax
171171internally sets the ``exclude `` property on the filter.
@@ -178,8 +178,60 @@ excluding those containing "World".
178178
179179 /api/articles/?title__contains=Hello&title__contains!=World
180180
181+ MethodFilter Reimplementation
182+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183+
184+ ``MethodFilter `` has been reimplemented to work across relationships. This is not a
185+ forwards-compatible change and requires adding a minimal amount of boilerplate to the
186+ filter method.
187+
188+ When filtering across relationships, the queryset and lookup value will be different.
189+ For example:
190+
191+ class PostFilter(filters.FilterSet):
192+ author = filters.RelatedFilter('AuthorFilter')
193+ is_published = filters.MethodFilter()
194+
195+ class Meta:
196+ model = Post
197+ fields = ['title', 'content']
198+
199+ def filter_is_published(self, name, qs, value):
200+ # convert value to boolean
201+ null = value.lower() != 'true'
202+
203+ # The lookup name will end with `is_published `, but could be
204+ # preceded by a related lookup path.
205+ if LOOKUP_SEP in name:
206+ rel, _ = name.rsplit(LOOKUP_SEP, 1)
207+ name = LOOKUP_SEP.join([rel, 'date_published__isnull'])
208+ else:
209+ name = 'date_published__isnull'
210+
211+ return qs.filter(**{name: null})
212+
213+ class AuthorFilter(filters.FilterSet):
214+ posts = filters.RelatedFilter('PostFilter')
215+
216+ class Meta:
217+ model = Author
218+ fields = ['name']
219+
220+ And given these API calls:
221+
222+ /api/posts/?is_published=true
223+
224+ /api/authors/?posts__is_published=true
225+
226+
227+ In the first API call, the filter method receives a queryset of posts. In the second,
228+ it receives a queryset of users. The filter method in the example modifies the lookup
229+ name to work across the relationship, allowing you to find published posts, or authors
230+ who have published posts.
231+
232+
181233DjangoFilterBackend
182- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234+ ~~~~~~~~~~~~~~~~~~~
183235
184236We implement our own subclass of ``DjangoFilterBackend ``, which you should probably use instead
185237of the default ``DjangoFilterBackend ``. Our ``DjangoFilterBackend `` caches repeated filter set
0 commit comments