Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5de570c

Browse files
n2ygksliverc
authored andcommitted
Add json api DjangoFilterBackend (django-json-api#466)
Implements django_filters.DjangoFilterBackend a Django ORM-style JSON:API filter[] implementation. See docs/usage.md for details.
1 parent 22c4587 commit 5de570c

File tree

15 files changed

+493
-33
lines changed

15 files changed

+493
-33
lines changed

‎.travis.yml‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,44 @@ cache: pip
55
matrix:
66
include:
77
- python: 2.7
8-
env: TOXENV=py27-django111-drf36
8+
env: TOXENV=py27-df11-django111-drf36
99
- python: 2.7
10-
env: TOXENV=py27-django111-drf37
10+
env: TOXENV=py27-df11-django111-drf37
1111
- python: 2.7
12-
env: TOXENV=py27-django111-drf38
12+
env: TOXENV=py27-df11-django111-drf38
1313

1414
- python: 3.4
15-
env: TOXENV=py34-django111-drf36
15+
env: TOXENV=py34-df20-django111-drf36
1616
- python: 3.4
17-
env: TOXENV=py34-django111-drf37
17+
env: TOXENV=py34-df20-django111-drf37
1818
- python: 3.4
19-
env: TOXENV=py34-django111-drf38
19+
env: TOXENV=py34-df20-django111-drf38
2020
- python: 3.4
21-
env: TOXENV=py34-django20-drf37
21+
env: TOXENV=py34-df20-django20-drf37
2222
- python: 3.4
23-
env: TOXENV=py34-django20-drf38
23+
env: TOXENV=py34-df20-django20-drf38
2424

2525
- python: 3.5
26-
env: TOXENV=py35-django111-drf36
26+
env: TOXENV=py35-df20-django111-drf36
2727
- python: 3.5
28-
env: TOXENV=py35-django111-drf37
28+
env: TOXENV=py35-df20-django111-drf37
2929
- python: 3.5
30-
env: TOXENV=py35-django111-drf38
30+
env: TOXENV=py35-df20-django111-drf38
3131
- python: 3.5
32-
env: TOXENV=py35-django20-drf37
32+
env: TOXENV=py35-df20-django20-drf37
3333
- python: 3.5
34-
env: TOXENV=py35-django20-drf38
34+
env: TOXENV=py35-df20-django20-drf38
3535

3636
- python: 3.6
37-
env: TOXENV=py36-django111-drf36
37+
env: TOXENV=py36-df20-django111-drf36
3838
- python: 3.6
39-
env: TOXENV=py36-django111-drf37
39+
env: TOXENV=py36-df20-django111-drf37
4040
- python: 3.6
41-
env: TOXENV=py36-django111-drf38
41+
env: TOXENV=py36-df20-django111-drf38
4242
- python: 3.6
43-
env: TOXENV=py36-django20-drf37
43+
env: TOXENV=py36-df20-django20-drf37
4444
- python: 3.6
45-
env: TOXENV=py36-django20-drf38
45+
env: TOXENV=py36-df20-django20-drf38
4646

4747
- python: 3.6
4848
env: TOXENV=flake8

‎CHANGELOG.md‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
* Add testing configuration to `REST_FRAMEWORK` configuration as described in [DRF](https://www.django-rest-framework.org/api-guide/testing/#configuration)
44
* Add `HyperlinkedRelatedField` and `SerializerMethodHyperlinkedRelatedField`. See [usage docs](docs/usage.md#related-fields)
55
* Add related urls support. See [usage docs](docs/usage.md#related-urls)
6-
* Replaced binary `drf_example` sqlite3 db with a [fixture](example/fixtures/drf_example.yaml). See [usage docs](docs/usage.md#running-the-example-app).
7-
* Add optional [jsonapi-style](http://jsonapi.org/format/) sort filter backend. See [usage docs](docs/usage.md#filter-backends)
6+
* Replaced binary `drf_example` sqlite3 db with a [fixture](example/fixtures/drf_example.yaml). See [getting started](docs/getting-started.md#running-the-example-app).
87
* For naming consistency, renamed new `JsonApi`-prefix pagination classes to `JSONAPI`-prefix.
98
* Deprecates `JsonApiPageNumberPagination` and `JsonApiLimitOffsetPagination`
109
* Performance improvement when rendering relationships with `ModelSerializer`
11-
10+
* Add optional [jsonapi-style](http://jsonapi.org/format/) filter backends. See [usage docs](docs/usage.md#filter-backends)
1211

1312
v2.5.0 - Released July 11, 2018
1413

‎README.rst‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ override ``settings.REST_FRAMEWORK``
173173
),
174174
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
175175
'DEFAULT_FILTER_BACKENDS': (
176-
'rest_framework_json_api.backends.JSONAPIOrderingFilter',
176+
'rest_framework_json_api.filters.JSONAPIOrderingFilter',
177+
'rest_framework_json_api.django_filters.DjangoFilterBackend',
177178
),
178179
'TEST_REQUEST_RENDERER_CLASSES': (
179180
'rest_framework_json_api.renderers.JSONRenderer',

‎docs/usage.md‎

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ REST_FRAMEWORK = {
3434
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
3535
'DEFAULT_FILTER_BACKENDS': (
3636
'rest_framework_json_api.filters.JSONAPIOrderingFilter',
37+
'rest_framework_json_api.django_filters.DjangoFilterBackend',
3738
),
3839
'TEST_REQUEST_RENDERER_CLASSES': (
3940
'rest_framework_json_api.renderers.JSONRenderer',
@@ -92,14 +93,14 @@ class MyLimitPagination(JSONAPILimitOffsetPagination):
9293

9394
### Filter Backends
9495

95-
_This is the first of several anticipated JSON:API-specific filter backends._
96+
_There are several anticipated JSON:API-specific filter backends in development. The first two are described below._
9697

9798
#### `JSONAPIOrderingFilter`
9899
`JSONAPIOrderingFilter` implements the [JSON:API `sort`](http://jsonapi.org/format/#fetching-sorting) and uses
99100
DRF's [ordering filter](http://django-rest-framework.readthedocs.io/en/latest/api-guide/filtering/#orderingfilter).
100101

101102
Per the JSON:API specification, "If the server does not support sorting as specified in the query parameter `sort`,
102-
it **MUST** return `400 Bad Request`." For example, for `?sort=`abc,foo,def` where `foo` is a valid
103+
it **MUST** return `400 Bad Request`." For example, for `?sort=abc,foo,def` where `foo` is a valid
103104
field name and the other two are not valid:
104105
```json
105106
{
@@ -118,18 +119,65 @@ field name and the other two are not valid:
118119
If you want to silently ignore bad sort fields, just use `rest_framework.filters.OrderingFilter` and set
119120
`ordering_param` to `sort`.
120121

122+
#### `DjangoFilterBackend`
123+
`DjangoFilterBackend` implements a Django ORM-style [JSON:API `filter`](http://jsonapi.org/format/#fetching-filtering)
124+
using the [django-filter](https://django-filter.readthedocs.io/) package.
125+
126+
This filter is not part of the JSON:API standard per-se, other than the requirement
127+
to use the `filter` keyword: It is an optional implementation of a style of
128+
filtering in which each filter is an ORM expression as implemented by
129+
`DjangoFilterBackend` and seems to be in alignment with an interpretation of the
130+
[JSON:API _recommendations_](http://jsonapi.org/recommendations/#filtering), including relationship
131+
chaining.
132+
133+
Filters can be:
134+
- A resource field equality test:
135+
`?filter[qty]=123`
136+
- Apply other [field lookup](https://docs.djangoproject.com/en/stable/ref/models/querysets/#field-lookups) operators:
137+
`?filter[name.icontains]=bar` or `?filter[name.isnull]=true`
138+
- Membership in a list of values:
139+
`?filter[name.in]=abc,123,zzz (name in ['abc','123','zzz'])`
140+
- Filters can be combined for intersection (AND):
141+
`?filter[qty]=123&filter[name.in]=abc,123,zzz&filter[...]`
142+
- A related resource path can be used:
143+
`?filter[inventory.item.partNum]=123456` (where `inventory.item` is the relationship path)
144+
145+
If you are also using [`rest_framework.filters.SearchFilter`](https://django-rest-framework.readthedocs.io/en/latest/api-guide/filtering/#searchfilter)
146+
(which performs single parameter searchs across multiple fields) you'll want to customize the name of the query
147+
parameter for searching to make sure it doesn't conflict with a field name defined in the filterset.
148+
The recommended value is: `search_param="filter[search]"` but just make sure it's
149+
`filter[_something_]` to comply with the jsonapi spec requirement to use the filter
150+
keyword. The default is "search" unless overriden.
151+
152+
The filter returns a `400 Bad Request` error for invalid filter query parameters as in this example
153+
for `GET http://127.0.0.1:8000/nopage-entries?filter[bad]=1`:
154+
```json
155+
{
156+
"errors": [
157+
{
158+
"detail": "invalid filter[bad]",
159+
"source": {
160+
"pointer": "/data"
161+
},
162+
"status": "400"
163+
}
164+
]
165+
}
166+
```
167+
121168
#### Configuring Filter Backends
122169

123170
You can configure the filter backends either by setting the `REST_FRAMEWORK['DEFAULT_FILTER_BACKENDS']` as shown
124-
in the [preceding](#configuration) example or individually add them as `.filter_backends` View attributes:
171+
in the [example settings](#configuration) or individually add them as `.filter_backends` View attributes:
125172

126173
```python
127174
from rest_framework_json_api import filters
175+
from rest_framework_json_api import django_filters
128176

129177
class MyViewset(ModelViewSet):
130178
queryset = MyModel.objects.all()
131179
serializer_class = MyModelSerializer
132-
filter_backends = (filters.JSONAPIOrderingFilter,)
180+
filter_backends = (filters.JSONAPIOrderingFilter, django_filters.DjangoFilterBackend,)
133181
```
134182

135183

‎example/requirements.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ pyparsing
1111
pytz
1212
six
1313
sqlparse
14-
14+
django-filter>=2.0

‎example/settings/dev.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
'polymorphic',
2727
'example',
2828
'debug_toolbar',
29+
'django_filters',
2930
]
3031

3132
TEMPLATES = [
@@ -90,6 +91,7 @@
9091
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
9192
'DEFAULT_FILTER_BACKENDS': (
9293
'rest_framework_json_api.filters.JSONAPIOrderingFilter',
94+
'rest_framework_json_api.django_filters.DjangoFilterBackend',
9395
),
9496
'TEST_REQUEST_RENDERER_CLASSES': (
9597
'rest_framework_json_api.renderers.JSONRenderer',

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /