Skip to content

Commit 8faa52b

Browse files
committed
Merge remote-tracking branch 'origin/develop' into develop
2 parents 5ae2757 + 9eba1de commit 8faa52b

File tree

1 file changed

+133
-2
lines changed

1 file changed

+133
-2
lines changed

README.md

+133-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,133 @@
1-
# graphene-django-filter
2-
Advanced filters for Graphene.
1+
# Graphene-Django-Filter
2+
[![CI](https://github.com/devind-team/graphene-django-filter/workflows/CI/badge.svg)](https://github.com/devind-team/graphene-django-filter/actions) [![PyPI version](https://badge.fury.io/py/graphene-django-filter.svg)](https://badge.fury.io/py/graphene-django-filter)
3+
4+
This package contains advanced filters for [graphene-django](https://github.com/graphql-python/graphene-django). The standard filtering feature in Graphene-Django relies on the Django-Filter library and therefore provides a flat API without the ability to use `and` and `or` expressions. This library makes the API nested and adds the `and` and `or` composition by extension of the `DjangoFilterConnectionField` field and the `FilterSet` class.
5+
# Requirements
6+
* Python (3.6, 3.7, 3.8, 3.9, 3.10)
7+
* Graphene-Django (2.15)
8+
# Features
9+
## Nested API with the ability to use `and` and `or` expressions
10+
To use, simply replace all `DjangoFilterConnectionField` fields with `AdvancedDjangoFilterConnectionField` fields in your queries. Also, if you create custom FilterSets, replace the inheritance from the `FilterSet` class with the inheritance from the `AdvancedFilterSet` class. For example, the following task query exposes an old flat API.
11+
```python
12+
import graphene
13+
from django_filters import FilterSet
14+
from graphene_django import DjangoObjectType
15+
from graphene_django.filter import DjangoFilterConnectionField
16+
17+
class TaskFilter(FilterSet)
18+
class Meta:
19+
model = Task
20+
fields = {
21+
'name': ('exact', 'contains'),
22+
'user__email': ('exact', 'contains'),
23+
'user__last_name': ('exact', 'contains'),
24+
}
25+
26+
class UserType(DjangoObjectType):
27+
class Meta:
28+
model = User
29+
interfaces = (graphene.relay.Node,)
30+
fields = '__all__'
31+
32+
class TaskType(DjangoObjectType):
33+
user = graphene.Field(UserType)
34+
35+
class Meta:
36+
model = Task
37+
interfaces = (graphene.relay.Node,)
38+
fields = '__all__'
39+
filterset_class = TaskFilter
40+
41+
class Query(graphene.ObjectType):
42+
tasks = DjangoFilterConnectionField(TaskType)
43+
```
44+
The flat API in which all filters are applied using the "and" operator looks like this.
45+
```graphql
46+
{
47+
tasks(
48+
name_Contains: "important"
49+
user_Email_Contains: "john"
50+
user_LastName: "Dou"
51+
){
52+
edges {
53+
node {
54+
id
55+
name
56+
}
57+
}
58+
}
59+
}
60+
```
61+
After replacing the field class with the `AdvancedDjangoFilterConnectionField` and the `FilterSet` class with the `AdvancedFilterSet` the API becomes nested with support for `and` and `or` expressions.
62+
```python
63+
from graphene_django_filter import AdvancedDjangoFilterConnectionField, AdvancedFilterSet
64+
65+
class TaskFilter(AdvancedFilterSet)
66+
class Meta:
67+
model = Task
68+
fields = {
69+
'name': ('exact', 'contains'),
70+
'user__email': ('exact', 'contains'),
71+
'user__last_name': ('exact', 'contains'),
72+
}
73+
74+
class Query(graphene.ObjectType):
75+
tasks = AdvancedDjangoFilterConnectionField(TaskType)
76+
```
77+
For example, the following query returns tasks whose names contain the word "important" or the user's email address contains the word "john" and the user's last name is "Dou". Note that the operators are applied to lookups such as `contains`, `exact`, etc. at the last level of nesting.
78+
```graphql
79+
{
80+
tasks(
81+
filter: {
82+
or: [
83+
{name: {contains: "important"}}
84+
and: [
85+
{user: email: {contains: "john"}}
86+
{user: lastName: {exact: "Dou"}}
87+
]
88+
]
89+
}
90+
){
91+
edges {
92+
node {
93+
id
94+
name
95+
}
96+
}
97+
}
98+
}
99+
```
100+
The same result can be achieved with an alternative query structure because within the same object the `and` operator is always used.
101+
```graphql
102+
{
103+
tasks(
104+
filter: {
105+
or: [
106+
{name: {contains: "important"}}
107+
{
108+
user: {
109+
email: {contains: "john"}
110+
lastName: {exact: "Dou"}
111+
}
112+
}
113+
]
114+
}
115+
){
116+
edges {
117+
node {
118+
id
119+
name
120+
}
121+
}
122+
}
123+
}
124+
```
125+
The filter input type has the following structure.
126+
```graphql
127+
input FilterInputType {
128+
and: [FilterInputType]
129+
or: [FilterInputType]
130+
...FieldLookups
131+
}
132+
```
133+
For more examples, see tests.

0 commit comments

Comments
 (0)