[1/4] compat: Handle older versions of django-filter

Submitted by Stephen Finucane on April 4, 2017, 9:38 p.m.

Details

Message ID 20170404213820.13350-1-stephen@that.guru
State Accepted
Headers show

Commit Message

Stephen Finucane April 4, 2017, 9:38 p.m.
Recent versions of Django REST Framework (DRF) have deprecated the
'DjangoFilterBackend' filter found in-tree, in favour of an equivalent
implementation found in django-filter. However, we need to support older
versions of DRF for users who want to use system packages.

Seeing as the two implementations are, for all intents and purposes,
essentially the same thing, provide a shim that will allow us to use
both together.

Signed-off-by: Stephen Finucane <stephen@that.guru>
Cc: Daniel Axtens <dja@axtens.net>
Partial-bug: #94
---
 patchwork/api/filters.py   |  5 +++--
 patchwork/compat.py        | 37 +++++++++++++++++++++++++++++++++++++
 patchwork/settings/base.py |  2 +-
 3 files changed, 41 insertions(+), 3 deletions(-)

Comments

Stephen Finucane April 28, 2017, 9:47 p.m.
On Tue, 2017-04-04 at 22:38 +0100, Stephen Finucane wrote:
> Recent versions of Django REST Framework (DRF) have deprecated the
> 'DjangoFilterBackend' filter found in-tree, in favour of an
> equivalent
> implementation found in django-filter. However, we need to support
> older
> versions of DRF for users who want to use system packages.
> 
> Seeing as the two implementations are, for all intents and purposes,
> essentially the same thing, provide a shim that will allow us to use
> both together.
> 
> Signed-off-by: Stephen Finucane <stephen@that.guru>
> Cc: Daniel Axtens <dja@axtens.net>
> Partial-bug: #94

I've gone ahead and merged all but the last of these (which served well
enough as a temporary test, but is tediously slow to keep around long
term).

Stephen

Patch hide | download patch | download mbox

diff --git a/patchwork/api/filters.py b/patchwork/api/filters.py
index eff7ceb..1573416 100644
--- a/patchwork/api/filters.py
+++ b/patchwork/api/filters.py
@@ -20,6 +20,7 @@ 
 from django_filters import FilterSet
 from django_filters import IsoDateTimeFilter
 
+from patchwork.compat import LOOKUP_FIELD
 from patchwork.models import Bundle
 from patchwork.models import Check
 from patchwork.models import CoverLetter
@@ -31,8 +32,8 @@  from patchwork.models import Series
 class TimestampMixin(FilterSet):
 
     # 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')
+    before = IsoDateTimeFilter(name='date', **{LOOKUP_FIELD: 'lt'})
+    since = IsoDateTimeFilter(name='date', **{LOOKUP_FIELD: 'gte'})
 
 
 class SeriesFilter(TimestampMixin, FilterSet):
diff --git a/patchwork/compat.py b/patchwork/compat.py
index 5c8ca23..af7d684 100644
--- a/patchwork/compat.py
+++ b/patchwork/compat.py
@@ -20,6 +20,7 @@ 
 """Compatibility wrappers for various Django versions."""
 
 import django
+from django.conf import settings
 
 
 # render_to_string
@@ -39,3 +40,39 @@  else:
         context_instance = RequestContext(request) if request else None
         return loader.render_to_string(template_name, context,
                                        context_instance)
+
+
+# DjangoFilterBackend
+#
+# The DjangoFilterBackend was provided in Django REST Framework from 3.0 to
+# 3.4, was marked as pending deprecation in 3.5, was deprecated in 3.6 and will
+# be removed in 3.7. However, the equivalent DjangoFilterBackend found in
+# django-filter is only available since 1.0 of that package.
+#
+# http://www.django-rest-framework.org/topics/3.6-announcement/
+
+if settings.ENABLE_REST_API:
+    import rest_framework  # noqa
+
+    if rest_framework.VERSION >= '3.5':
+        from django_filters.rest_framework import DjangoFilterBackend  # noqa
+    else:
+        from rest_framework.filters import DjangoFilterBackend  # noqa
+
+
+# LOOKUP_FIELD
+#
+# The django-filter library uses the 'lookup_expr' attribute to determine which
+# lookup type to use, e.g. exact, gt, lt etc. However, until 0.13 this was
+# called 'lookup_type', and 0.13 supported both but gave a deprecation warning.
+# We need to support these versions for use with older versions of DRF.
+#
+# https://github.com/carltongibson/django-filter/blob/v0.13/django_filters\
+#   /filters.py#L35-L36
+if settings.ENABLE_REST_API:
+    import django_filters  # noqa
+
+    if django_filters.VERSION >= (1, 0):
+        LOOKUP_FIELD = 'lookup_expr'
+    else:
+        LOOKUP_FIELD = 'lookup_type'
diff --git a/patchwork/settings/base.py b/patchwork/settings/base.py
index 180a469..5d5caf1 100644
--- a/patchwork/settings/base.py
+++ b/patchwork/settings/base.py
@@ -147,7 +147,7 @@  REST_FRAMEWORK = {
         'rest_framework.versioning.NamespaceVersioning',
     'DEFAULT_PAGINATION_CLASS': 'patchwork.api.base.LinkHeaderPagination',
     'DEFAULT_FILTER_BACKENDS': (
-        'django_filters.rest_framework.DjangoFilterBackend',
+        'patchwork.compat.DjangoFilterBackend',
         'rest_framework.filters.SearchFilter',
         'rest_framework.filters.OrderingFilter',
     ),