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