[RFC 1/2] REST: Integrate django-filter support

Stephen Finucane stephen at that.guru
Thu Nov 17 12:47:22 AEDT 2016


This mostly works out of the box, thanks to Django REST Framework.
Mostly unique fields, like name or email, are excluded as these will be
handled separately.

Signed-off-by: Stephen Finucane <stephen at that.guru>
---
I need to disable django-filter support when it's not available.
However, its use would allow us to get rid of most of 'filters.py'.
Is this worth introducing a compulsory dependency for?
---
 patchwork/api/check.py     |  2 ++
 patchwork/api/cover.py     |  2 ++
 patchwork/api/patch.py     |  2 ++
 patchwork/api/series.py    |  3 ++-
 patchwork/filters.py       | 41 +++++++++++++++++++++++++++++++++++++++++
 patchwork/settings/base.py |  6 +++++-
 requirements-test.txt      |  2 +-
 7 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/patchwork/api/check.py b/patchwork/api/check.py
index 43463fe..2f0d5fd 100644
--- a/patchwork/api/check.py
+++ b/patchwork/api/check.py
@@ -27,6 +27,7 @@ from rest_framework.serializers import HyperlinkedModelSerializer
 from rest_framework.serializers import HyperlinkedIdentityField
 
 from patchwork.api import MultipleFieldLookupMixin
+from patchwork.filters import CheckFilter
 from patchwork.models import Check
 from patchwork.models import Patch
 
@@ -89,6 +90,7 @@ class CheckMixin(object):
 
     queryset = Check.objects.prefetch_related('patch', 'user')
     serializer_class = CheckSerializer
+    filter_class = CheckFilter
 
 
 class CheckListCreate(CheckMixin, ListCreateAPIView):
diff --git a/patchwork/api/cover.py b/patchwork/api/cover.py
index 2674be3..189e2ed 100644
--- a/patchwork/api/cover.py
+++ b/patchwork/api/cover.py
@@ -25,6 +25,7 @@ from rest_framework.serializers import HyperlinkedModelSerializer
 from rest_framework.serializers import HyperlinkedRelatedField
 from rest_framework.serializers import SerializerMethodField
 
+from patchwork.filters import CoverLetterFilter
 from patchwork.models import CoverLetter
 
 
@@ -67,6 +68,7 @@ class CoverLetterList(ListAPIView):
     queryset = CoverLetter.objects.all().prefetch_related(
         'series').select_related('submitter').defer('content', 'headers')
     serializer_class = CoverLetterListSerializer
+    filter_class = CoverLetterFilter
 
 
 class CoverLetterDetail(RetrieveAPIView):
diff --git a/patchwork/api/patch.py b/patchwork/api/patch.py
index 8d308e8..149b3ae 100644
--- a/patchwork/api/patch.py
+++ b/patchwork/api/patch.py
@@ -29,6 +29,7 @@ from rest_framework.serializers import SerializerMethodField
 
 from patchwork.api import PatchworkPermission
 from patchwork.api import STATE_CHOICES
+from patchwork.filters import PatchFilter
 from patchwork.models import Patch
 from patchwork.models import State
 
@@ -118,6 +119,7 @@ class PatchList(ListAPIView):
         'content', 'diff', 'headers')
     permission_classes = (PatchworkPermission,)
     serializer_class = PatchListSerializer
+    filter_class = PatchFilter
 
 
 class PatchDetail(RetrieveUpdateAPIView):
diff --git a/patchwork/api/series.py b/patchwork/api/series.py
index fead4ca..9771bf4 100644
--- a/patchwork/api/series.py
+++ b/patchwork/api/series.py
@@ -22,6 +22,7 @@ from rest_framework.generics import RetrieveAPIView
 from rest_framework.serializers import HyperlinkedModelSerializer
 
 from patchwork.api import PatchworkPermission
+from patchwork.filters import SeriesFilter
 from patchwork.models import Series
 
 
@@ -51,7 +52,7 @@ class SeriesMixin(object):
 class SeriesList(SeriesMixin, ListAPIView):
     """List series."""
 
-    pass
+    filter_class = SeriesFilter
 
 
 class SeriesDetail(SeriesMixin, RetrieveAPIView):
diff --git a/patchwork/filters.py b/patchwork/filters.py
index bc8ca41..5eb833f 100644
--- a/patchwork/filters.py
+++ b/patchwork/filters.py
@@ -24,7 +24,13 @@ from django.utils.html import escape
 from django.utils.safestring import mark_safe
 from django.utils import six
 from django.utils.six.moves.urllib.parse import quote
+from django_filters import CharFilter
+from django_filters import FilterSet
+from django_filters import IsoDateTimeFilter
 
+from patchwork.models import Check
+from patchwork.models import CoverLetter
+from patchwork.models import Patch
 from patchwork.models import Person
 from patchwork.models import Series
 from patchwork.models import State
@@ -505,3 +511,38 @@ class Filters:
             if isinstance(f, filterclass):
                 f.set_status(*args, **kwargs)
                 return
+
+
+class TimestampMixin(object):
+
+    # TODO(stephenfin): These should filter on a 'updated_at' field instead
+    before = IsoDateTimeFilter(name='date', lookup_expr='lt')
+    since = IsoDateTimeFilter(name='date', lookup_expr='gte')
+
+
+class SeriesFilter(TimestampMixin, FilterSet):
+
+    class Meta:
+        model = Series
+        fields = ['submitter']
+
+
+class CoverLetterFilter(TimestampMixin, FilterSet):
+
+    class Meta:
+        model = CoverLetter
+        fields = ['series', 'submitter']
+
+
+class PatchFilter(FilterSet):
+
+    class Meta:
+        model = Patch
+        fields = ['series', 'submitter', 'delegate', 'state', 'archived']
+
+
+class CheckFilter(TimestampMixin, FilterSet):
+
+    class Meta:
+        model = Check
+        fields = ['user', 'state', 'context']
diff --git a/patchwork/settings/base.py b/patchwork/settings/base.py
index 35ac96a..dd2d3d0 100644
--- a/patchwork/settings/base.py
+++ b/patchwork/settings/base.py
@@ -133,7 +133,8 @@ try:
     import rest_framework  # NOQA
 
     INSTALLED_APPS += [
-        'rest_framework'
+        'rest_framework',
+        'django_filters',
     ]
 except ImportError:
     pass
@@ -144,6 +145,9 @@ REST_FRAMEWORK = {
         'rest_framework.versioning.NamespaceVersioning'
     ),
     'DEFAULT_PAGINATION_CLASS': 'patchwork.api.LinkHeaderPagination',
+    'DEFAULT_FILTER_BACKENDS': (
+        'django_filters.rest_framework.DjangoFilterBackend',
+    )
 }
 
 #
diff --git a/requirements-test.txt b/requirements-test.txt
index 7cb5ae9..c664976 100644
--- a/requirements-test.txt
+++ b/requirements-test.txt
@@ -3,4 +3,4 @@ django-debug-toolbar==1.5
 python-dateutil>2.0,<3.0
 selenium>2.0,<3.0
 djangorestframework>=3.4,<3.5
-drf-nested-routers>=0.11.1,<0.12
+django-filter>=0.15,<0.16
-- 
2.7.4



More information about the Patchwork mailing list