File: rest_framework.txt

package info (click to toggle)
django-filter 25.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,228 kB
  • sloc: python: 7,970; javascript: 7,213; makefile: 157; sh: 16
file content (174 lines) | stat: -rw-r--r-- 5,603 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
.. _drf integration:

====================
Integration with DRF
====================

Integration with `Django Rest Framework`__ is provided through a DRF-specific ``FilterSet`` and a `filter backend`__. These may be found in the ``rest_framework`` sub-package.

__ http://www.django-rest-framework.org/
__ http://www.django-rest-framework.org/api-guide/filtering/

Quickstart
----------

Using the new ``FilterSet`` simply requires changing the import path. Instead of importing from ``django_filters``, import from the ``rest_framework`` sub-package.

.. code-block:: python

    from django_filters import rest_framework as filters

    class ProductFilter(filters.FilterSet):
        ...

Your view class will also need to add ``DjangoFilterBackend`` to the ``filter_backends``.

.. code-block:: python

    from django_filters import rest_framework as filters

    class ProductList(generics.ListAPIView):
        queryset = Product.objects.all()
        serializer_class = ProductSerializer
        filter_backends = (filters.DjangoFilterBackend,)
        filterset_fields = ('category', 'in_stock')

If you want to use the django-filter backend by default, add it to the ``DEFAULT_FILTER_BACKENDS`` setting.

.. code-block:: python

    # settings.py
    INSTALLED_APPS = [
        # ...
        'rest_framework',
        'django_filters',
    ]

    REST_FRAMEWORK = {
        'DEFAULT_FILTER_BACKENDS': (
            'django_filters.rest_framework.DjangoFilterBackend',
            # ...
        ),
    }


Adding a FilterSet with ``filterset_class``
-------------------------------------------

To enable filtering with a ``FilterSet``, add it to the ``filterset_class`` parameter on your view class.

.. code-block:: python

    from rest_framework import generics
    from django_filters import rest_framework as filters
    from myapp import Product


    class ProductFilter(filters.FilterSet):
        min_price = filters.NumberFilter(field_name="price", lookup_expr='gte')
        max_price = filters.NumberFilter(field_name="price", lookup_expr='lte')

        class Meta:
            model = Product
            fields = ['category', 'in_stock']


    class ProductList(generics.ListAPIView):
        queryset = Product.objects.all()
        serializer_class = ProductSerializer
        filter_backends = (filters.DjangoFilterBackend,)
        filterset_class = ProductFilter


Using the ``filterset_fields`` shortcut
---------------------------------------

You may bypass creating a ``FilterSet`` by instead adding ``filterset_fields`` to your view class. This is equivalent to creating a ``FilterSet`` with just :ref:`Meta.fields <fields>`.


.. code-block:: python

    from rest_framework import generics
    from django_filters import rest_framework as filters
    from myapp import Product


    class ProductList(generics.ListAPIView):
        queryset = Product.objects.all()
        filter_backends = (filters.DjangoFilterBackend,)
        filterset_fields = ('category', 'in_stock')


    # Equivalent FilterSet:
    class ProductFilter(filters.FilterSet):
        class Meta:
            model = Product
            fields = ('category', 'in_stock')


Note that using ``filterset_fields`` and ``filterset_class`` together is not
supported.


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 BookFilter(filters.FilterSet):
        def __init__(self, *args, author=None, **kwargs):
            super().__init__(*args, **kwargs)
            # do something w/ author


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

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


Crispy Forms
------------

If you are using DRF's browsable API or admin API you may also want to install ``django-crispy-forms``, which will enhance the presentation of the filter forms in HTML views, by allowing them to render Bootstrap 3 HTML. Note that this isn't actively supported, although pull requests for bug fixes are welcome.

.. code-block:: bash

    pip install django-crispy-forms

With crispy forms installed and added to Django's ``INSTALLED_APPS``, the browsable API will present a filtering control for ``DjangoFilterBackend``, like so:

.. image:: ../assets/form.png


Additional ``FilterSet`` Features
---------------------------------

The following features are specific to the rest framework FilterSet:

- ``BooleanFilter``'s use the API-friendly ``BooleanWidget``, which accepts lowercase ``true``/``false``.
- Filter generation uses ``IsoDateTimeFilter`` for datetime model fields.
- Raised ``ValidationError``'s are reraised as their DRF equivalent.