@@ -113,15 +113,15 @@ You can easily traverse multiple relationships when filtering by using ``Related
113113
114114
115115 class DepartmentFilter(filters.FilterSet):
116- manager = filters.RelatedFilter(ManagerFilter, name = ' manager' )
116+ manager = filters.RelatedFilter(ManagerFilter, name = ' manager' , queryset = Manager.objects.all() )
117117
118118 class Meta:
119119 model = Department
120120 fields = {' name' : [' exact' , ' in' , ' startswith' ]}
121121
122122
123123 class CompanyFilter(filters.FilterSet):
124- department = filters.RelatedFilter(DepartmentFilter, name = ' department' )
124+ department = filters.RelatedFilter(DepartmentFilter, name = ' department' , queryset = Department.objects.all() )
125125
126126 class Meta:
127127 model = Company
@@ -140,13 +140,32 @@ Example filter calls:
140140 / api/ companies? department__name=Accounting
141141 / api/ companies? department__manager__name__startswith=Bob
142142
143+ `` queryset`` callables
144+ """ """ """ """ """ """ """ "
145+
146+ Since ``RelatedFilter`` is a subclass of ``ModelChoiceFilter``, the ``queryset`` argument supports callable behavior.
147+ In the following example, the set of departments is restricted to those in the user's company.
148+
149+ .. code-block:: python
150+
151+ def departments(request):
152+ company = request.user.company
153+ return company.department_set.all()
154+
155+ class EmployeeFilter(filters.FilterSet):
156+ department = filters.RelatedFilter(filterset=DepartmentFilter, queryset=departments)
157+ ...
158+
159+ Recursive relationships
160+ """ """ """ """ """ """ """ " "
161+
143162Recursive relations are also supported. It may be necessary to specify the full module path.
144163
145164.. code- block:: python
146165
147166 class PersonFilter(filters.FilterSet):
148167 name = filters.AllLookupsFilter(name = ' name' )
149- best_friend = filters.RelatedFilter(' people.views.PersonFilter' , name = ' best_friend' )
168+ best_friend = filters.RelatedFilter(' people.views.PersonFilter' , name = ' best_friend' , queryset = Person.objects.all() )
150169
151170 class Meta:
152171 model = Person
@@ -185,7 +204,7 @@ to all filter classes. It incorporates some of the implementation details of the
185204 return qs.filter(** {lookup_expr: isnull})
186205
187206 class AuthorFilter(filters.FilterSet):
188- posts = filters.RelatedFilter(' PostFilter' )
207+ posts = filters.RelatedFilter(' PostFilter' , queryset = Post.objects.all() )
189208
190209 class Meta:
191210 model = Author
@@ -285,15 +304,15 @@ You cannot combine ``AllLookupsFilter`` with ``RelatedFilter`` as the filter nam
285304.. code- block:: python
286305
287306 class ProductFilter(filters.FilterSet):
288- manufacturer = filters.RelatedFilter(' ManufacturerFilter' )
307+ manufacturer = filters.RelatedFilter(' ManufacturerFilter' , queryset = Manufacturer.objects.all() )
289308 manufacturer = filters.AllLookupsFilter()
290309
291310To work around this, you have the following options:
292311
293312.. code- block:: python
294313
295314 class ProductFilter(filters.FilterSet):
296- manufacturer = filters.RelatedFilter(' ManufacturerFilter' )
315+ manufacturer = filters.RelatedFilter(' ManufacturerFilter' , queryset = Manufacturer.objects.all() )
297316
298317 class Meta:
299318 model = Product
@@ -304,7 +323,7 @@ To work around this, you have the following options:
304323 # or
305324
306325 class ProductFilter(filters.FilterSet):
307- manufacturer = filters.RelatedFilter(' ManufacturerFilter' , lookups = ' __all__' ) # `lookups` also accepts a list
326+ manufacturer = filters.RelatedFilter(' ManufacturerFilter' , queryset = Manufacturer.objects.all(), lookups = ' __all__' ) # `lookups` also accepts a list
308327
309328 class Meta:
310329 model = Product
@@ -326,15 +345,15 @@ and ``FilterSet``s from either package are compatible with the other's DRF backe
326345 ...
327346
328347 class DRFFilter(rest_framework_filters.FilterSet):
329- vanilla = rest_framework_filters.RelatedFilter(filterset = VanillaFilter)
348+ vanilla = rest_framework_filters.RelatedFilter(filterset = VanillaFilter, queryset = ... )
330349
331350
332351 # invalid
333352 class DRFFilter(rest_framework_filters.FilterSet):
334353 ...
335354
336355 class VanillaFilter(django_filters.FilterSet):
337- drf = rest_framework_filters.RelatedFilter(filterset = DRFFilter)
356+ drf = rest_framework_filters.RelatedFilter(filterset = DRFFilter, queryset = ... )
338357
339358
340359Caveats & Limitations
@@ -380,6 +399,22 @@ The recommended solutions are to either:
380399 ? publish_date__range=2016 - 01 - 01 ,2016 - 02 - 01
381400
382401
402+ Migrating to 1.0
403+ ----------------
404+
405+ `` RelatedFilter.queryset`` now required
406+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
407+
408+ The related filterset' s model is no longer used to provide the default value for ``RelatedFilter.queryset``. This
409+ change reduces the chance of unintentionally exposing data in the rendered filter forms. You must now explicitly
410+ provide the `` queryset`` argument, or override the `` get_queryset()`` method (see `queryset callables` _).
411+
412+
413+ `` get_filters()`` renamed to `` expand_filters()``
414+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
415+
416+ django- filter has add a `` get_filters()`` classmethod to it' s API, so this method has been renamed.
417+
383418License
384419------ -
385420Copyright (c) 2013 - 2015 Philip Neustrom < philipn@ gmail.com> ,
0 commit comments