Skip to content

Commit bc59d0a

Browse files
authored
Merge pull request #232 from basilfx/master
Pass context object to FilterSet for request-baed filtering
2 parents 9e26aaf + 4bdcf05 commit bc59d0a

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

docs/filtering.rst

+20
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,23 @@ create your own ``Filterset`` as follows:
126126
# We specify our custom AnimalFilter using the filterset_class param
127127
all_animals = DjangoFilterConnectionField(AnimalNode,
128128
filterset_class=AnimalFilter)
129+
130+
The context argument is passed on as the `request argument <http://django-filter.readthedocs.io/en/latest/guide/usage.html#request-based-filtering>`__
131+
in a ``django_filters.FilterSet`` instance. You can use this to customize your
132+
filters to be context-dependent. We could modify the ``AnimalFilter`` above to
133+
pre-filter animals owned by the authenticated user (set in ``context.user``).
134+
135+
.. code:: python
136+
137+
class AnimalFilter(django_filters.FilterSet):
138+
# Do case-insensitive lookups on 'name'
139+
name = django_filters.CharFilter(lookup_type='iexact')
140+
141+
class Meta:
142+
model = Animal
143+
fields = ['name', 'genus', 'is_domesticated']
144+
145+
@property
146+
def qs(self):
147+
# The query context can be found in self.request.
148+
return super(AnimalFilter, self).filter(owner=self.request.user)

graphene_django/filter/fields.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ def connection_resolver(cls, resolver, connection, default_manager, max_limit,
7272
filter_kwargs = {k: v for k, v in args.items() if k in filtering_args}
7373
qs = filterset_class(
7474
data=filter_kwargs,
75-
queryset=default_manager.get_queryset()
75+
queryset=default_manager.get_queryset(),
76+
request=context
7677
).qs
7778

7879
return super(DjangoFilterConnectionField, cls).connection_resolver(

graphene_django/filter/tests/test_fields.py

+42
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,48 @@ def test_filter_shortcut_filterset_extra_meta():
140140
assert 'headline' not in field.filterset_class.get_fields()
141141

142142

143+
def test_filter_shortcut_filterset_context():
144+
class ArticleContextFilter(django_filters.FilterSet):
145+
146+
class Meta:
147+
model = Article
148+
exclude = set()
149+
150+
@property
151+
def qs(self):
152+
qs = super(ArticleContextFilter, self).qs
153+
return qs.filter(reporter=self.request.reporter)
154+
155+
class Query(ObjectType):
156+
context_articles = DjangoFilterConnectionField(ArticleNode, filterset_class=ArticleContextFilter)
157+
158+
r1 = Reporter.objects.create(first_name='r1', last_name='r1', email='[email protected]')
159+
r2 = Reporter.objects.create(first_name='r2', last_name='r2', email='[email protected]')
160+
Article.objects.create(headline='a1', pub_date=datetime.now(), reporter=r1, editor=r1)
161+
Article.objects.create(headline='a2', pub_date=datetime.now(), reporter=r2, editor=r2)
162+
163+
class context(object):
164+
reporter = r2
165+
166+
query = '''
167+
query {
168+
contextArticles {
169+
edges {
170+
node {
171+
headline
172+
}
173+
}
174+
}
175+
}
176+
'''
177+
schema = Schema(query=Query)
178+
result = schema.execute(query, context_value=context())
179+
assert not result.errors
180+
181+
assert len(result.data['contextArticles']['edges']) == 1
182+
assert result.data['contextArticles']['edges'][0]['node']['headline'] == 'a2'
183+
184+
143185
def test_filter_filterset_information_on_meta():
144186
class ReporterFilterNode(DjangoObjectType):
145187

0 commit comments

Comments
 (0)