Skip to content

Commit c733b38

Browse files
committed
Merge pull request #60 from adamcharnock/feature/django
Django integration implementation
2 parents a7c28f2 + 2264c3d commit c733b38

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1702
-123
lines changed

.editorconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# http://editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
charset = utf-8
7+
end_of_line = lf
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
11+
[*.{py,rst,ini}]
12+
indent_style = space
13+
indent_size = 4
14+

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,9 @@ target/
7272
/docs/static/playground/lib
7373

7474
/docs/static/playground
75+
76+
# PyCharm
77+
.idea
78+
79+
# Databases
80+
*.sqlite3

.travis.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ language: python
22
sudo: false
33
python:
44
- 2.7
5-
- 3.3
65
- 3.4
76
- 3.5
87
- pypy
@@ -24,8 +23,9 @@ before_install:
2423
install:
2524
- |
2625
if [ "$TEST_TYPE" = build ]; then
27-
pip install --download-cache $HOME/.cache/pip/ pytest pytest-cov coveralls six pytest-django
26+
pip install --download-cache $HOME/.cache/pip/ pytest pytest-cov coveralls six pytest-django django-filter
2827
pip install --download-cache $HOME/.cache/pip/ -e .[django]
28+
pip install django==$DJANGO_VERSION
2929
python setup.py develop
3030
elif [ "$TEST_TYPE" = build_website ]; then
3131
pip install --download-cache $HOME/.cache/pip/ -e .
@@ -79,6 +79,14 @@ env:
7979
matrix:
8080
fast_finish: true
8181
include:
82+
- python: '2.7'
83+
env: TEST_TYPE=build DJANGO_VERSION=1.6
84+
- python: '2.7'
85+
env: TEST_TYPE=build DJANGO_VERSION=1.7
86+
- python: '2.7'
87+
env: TEST_TYPE=build DJANGO_VERSION=1.8
88+
- python: '2.7'
89+
env: TEST_TYPE=build DJANGO_VERSION=1.9
8290
- python: '2.7'
8391
env: TEST_TYPE=build_website
8492
- python: '2.7'

bin/autolinter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/bin/bash
22

3+
# Install the required scripts with
4+
# pip install autoflake autopep8 isort
35
autoflake ./examples/ ./graphene/ -r --remove-unused-variables --remove-all-unused-imports --in-place
46
autopep8 ./examples/ ./graphene/ -r --in-place --experimental --aggressive --max-line-length 120
57
isort -rc ./examples/ ./graphene/

docs/config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ ga = "UA-12613282-7"
1616
"/docs/mutations/",
1717
"/docs/basic-types/",
1818
"/docs/relay/",
19+
"/docs/filtering/",
1920
]

docs/pages/docs/filtering.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
---
2+
title: Filtering (Django)
3+
description: Details of how to perform filtering
4+
---
5+
6+
# Filtering (Django)
7+
8+
Graphene integrates with [django-filter](https://django-filter.readthedocs.org)
9+
to provide filtering of results. See the
10+
[usage documentation](https://django-filter.readthedocs.org/en/latest/usage.html#the-filter)
11+
for details on the format for `filter_fields`.
12+
13+
This filtering is only available when using the Django integrations
14+
(i.e. nodes which extend `DjangoNode`). Additionally `django-filter`
15+
is an optional dependency of Graphene. You will need to
16+
install it manually, which can be done as follows:
17+
18+
```bash
19+
# You'll need to django-filter
20+
pip install django-filter
21+
```
22+
23+
**Note: The techniques below are demoed in the
24+
[cookbook example app](https://github.com/graphql-python/graphene/tree/feature/django/examples/cookbook).**
25+
26+
## Filterable fields
27+
28+
The `filter_fields` parameter is used to specify the fields which can be filtered upon.
29+
The value specified here is passed directly to `django-filter`, so see the
30+
[filtering documentation](https://django-filter.readthedocs.org/en/latest/usage.html#the-filter)
31+
for full details on the range of options available.
32+
33+
For example:
34+
35+
```python
36+
class AnimalNode(DjangoNode):
37+
class Meta:
38+
# Assume you have an Animal model defined with the following fields
39+
model = Animal
40+
filter_fields = ['name', 'genus', 'is_domesticated']
41+
42+
class Query(ObjectType):
43+
animal = relay.NodeField(AnimalNode)
44+
all_animals = DjangoFilterConnectionField(AnimalNode)
45+
```
46+
47+
You could then perform a query such as:
48+
49+
```graphql
50+
query {
51+
# Note that fields names become camelcased
52+
allAnimals(genus: "cat", isDomesticated: true) {
53+
edges {
54+
node {
55+
id,
56+
name
57+
}}}}
58+
```
59+
60+
You can also make more complex lookup types available:
61+
62+
```python
63+
class AnimalNode(DjangoNode):
64+
class Meta:
65+
model = Animal
66+
# Provide more complex lookup types
67+
filter_fields = {
68+
'name': ['exact', 'icontains', 'istartswith'],
69+
'genus': ['exact'],
70+
'is_domesticated': ['exact'],
71+
}
72+
```
73+
74+
Which you could query as follows:
75+
76+
```graphql
77+
query {
78+
# Note that fields names become camelcased
79+
allAnimals(nameIcontains: "lion") {
80+
edges {
81+
node {
82+
id,
83+
name
84+
}}}}
85+
```
86+
87+
## Orderable fields
88+
89+
Ordering can also be specified using `filter_order_by`. Like `filter_fields`,
90+
this value is also passed directly to `django-filter` as the `order_by` field.
91+
For full details see the
92+
[order_by documentation](https://django-filter.readthedocs.org/en/latest/usage.html#ordering-using-order-by).
93+
94+
For example:
95+
96+
```python
97+
class AnimalNode(DjangoNode):
98+
class Meta:
99+
model = Animal
100+
filter_fields = ['name', 'genus', 'is_domesticated']
101+
# Either a tuple/list of fields upon which ordering is allowed, or
102+
# True to allow filtering on all fields specified in filter_fields
103+
order_by_fields = True
104+
```
105+
106+
You can then control the ordering via the `orderBy` argument:
107+
108+
```graphql
109+
query {
110+
allAnimals(orderBy: "name") {
111+
edges {
112+
node {
113+
id,
114+
name
115+
}}}}
116+
```
117+
118+
## Custom Filtersets
119+
120+
By default Graphene provides easy access to the most commonly used
121+
features of `django-filter`. This is done by transparently creating a
122+
`django_filters.FilterSet` class for you and passing in the values for
123+
`filter_fields` and `order_by_fields`.
124+
125+
However, you may find this to be insufficient. In these cases you can
126+
create your own `Filterset` as follows:
127+
128+
```python
129+
class AnimalNode(DjangoNode):
130+
class Meta:
131+
# Assume you have an Animal model defined with the following fields
132+
model = Animal
133+
filter_fields = ['name', 'genus', 'is_domesticated']
134+
135+
136+
class AnimalFilter(django_filters.FilterSet):
137+
# Do case-insensitive lookups on 'name'
138+
name = django_filters.CharFilter(lookup_type='iexact')
139+
140+
class Meta:
141+
model = Animal
142+
fields = ['name', 'genus', 'is_domesticated']
143+
144+
145+
class Query(ObjectType):
146+
animal = relay.NodeField(AnimalNode)
147+
# We specify our custom AnimalFilter using the filterset_class param
148+
all_animals = DjangoFilterConnectionField(AnimalNode,
149+
filterset_class=AnimalFilter)
150+
```

0 commit comments

Comments
 (0)