Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor backend filterset instantiation #865

Merged
merged 2 commits into from
Jul 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions django_filters/rest_framework/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ def template(self):
return 'django_filters/rest_framework/crispy_form.html'
return 'django_filters/rest_framework/form.html'

def get_filterset(self, request, queryset, view):
filterset_class = self.get_filterset_class(view, queryset)
if filterset_class is None:
return None

kwargs = self.get_filterset_kwargs(request, queryset, view)
return filterset_class(**kwargs)

def get_filterset_class(self, view, queryset=None):
"""
Return the `FilterSet` class used to filter the queryset.
Expand Down Expand Up @@ -71,27 +79,29 @@ class Meta(MetaBase):

return None

def get_filterset_kwargs(self, request, queryset, view):
return {
'data': request.query_params,
'queryset': queryset,
'request': request,
}

def filter_queryset(self, request, queryset, view):
filterset_class = self.get_filterset_class(view, queryset)
filterset = self.get_filterset(request, queryset, view)
if filterset is None:
return queryset

if filterset_class:
filterset = filterset_class(request.query_params, queryset=queryset, request=request)
if not filterset.is_valid() and self.raise_exception:
raise utils.translate_validation(filterset.errors)
return filterset.qs
return queryset
if not filterset.is_valid() and self.raise_exception:
raise utils.translate_validation(filterset.errors)
return filterset.qs

def to_html(self, request, queryset, view):
filterset_class = self.get_filterset_class(view, queryset)
if not filterset_class:
filterset = self.get_filterset(request, queryset, view)
if filterset is None:
return None
filterset = filterset_class(request.query_params, queryset=queryset, request=request)

template = loader.get_template(self.template)
context = {
'filter': filterset
}

context = {'filter': filterset}
return template.render(context, request)

def get_coreschema_field(self, field):
Expand Down
39 changes: 39 additions & 0 deletions docs/guide/rest_framework.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,45 @@ You may bypass creating a ``FilterSet`` by instead adding ``filter_fields`` to y
fields = ('category', 'in_stock')


Overriding FilterSet creation
-----------------------------

``FilterSet`` creation can be customized by overriding the following methods on the backend class:

* ``.get_filterset(self, request, queryset, view)``
* ``.get_filterset_class(self, view, queryset=None)``
* ``.get_filterset_kwargs(self, request, queryset, view)``

You can override these methods on a case-by-case basis for each view, creating unique backends, or these methods can be used to write your own hooks to the view class.

.. code-block:: python

class MyFilterBackend(filters.DjangoFilterBackend):
def get_filterset_kwargs(self, request, queryset, view):
kwargs = super().get_filterset_kwargs(request, queryset, view)

# merge filterset kwargs provided by view class
if hasattr(view, 'get_filterset_kwargs'):
kwargs.update(view.get_filterset_kwargs())

return kwargs


class BooksFilter(filters.FitlerSet):
def __init__(self, *args, author=None, **kwargs):
super().__init__(*args, **kwargs)
# do something w/ author


class BookViewSet(viewsets.ModelViewSet):
filter_backends = [MyFilterBackend]
filter_class = BookFilter

def get_filteset_kwargs(self):
return {
'author': self.get_author(),
}

Schema Generation with Core API
-------------------------------

Expand Down