From 828e59ccc99d8c2751460c5c8155dba20972b257 Mon Sep 17 00:00:00 2001
From: Alan Crosswell <alan@columbia.edu>
Date: Fri, 31 May 2019 16:40:45 -0400
Subject: [PATCH 1/4] implement
 DjangoFilterBackend.get_schema_operation_parameters

---
 .../django_filters/backends.py                | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/rest_framework_json_api/django_filters/backends.py b/rest_framework_json_api/django_filters/backends.py
index 347acb58..58ac1a75 100644
--- a/rest_framework_json_api/django_filters/backends.py
+++ b/rest_framework_json_api/django_filters/backends.py
@@ -1,4 +1,5 @@
 import re
+import warnings
 
 from django_filters import VERSION
 from django_filters.rest_framework import DjangoFilterBackend
@@ -142,3 +143,31 @@ def filter_queryset(self, request, queryset, view):
             return filter_class(kwargs['data'], queryset=queryset, request=request).qs
 
         return queryset
+
+    def get_schema_operation_parameters(self, view):
+        """
+        Return Open API query parameter schema.
+        """
+        # TODO: Update this to extend the upstream django-filter implemntation if and when that gets merged.
+        # see https://github.com/carltongibson/django-filter/pull/1086
+
+        try:
+            queryset = view.get_queryset()
+        except Exception:
+            queryset = None
+            warnings.warn(
+                "{} is not compatible with schema generation".format(view.__class__)
+            )
+
+        filterset_class = self.get_filterset_class(view, queryset)
+        return [] if not filterset_class else [
+            ({
+                'name': 'filter[{}]'.format(field_name.replace('__', '.')),
+                'required': field.extra['required'],
+                'in': 'query',
+                'description': field.label if field.label is not None else field_name,
+                'schema': {
+                    'type': 'string',
+                },
+            }) for field_name, field in filterset_class.base_filters.items()
+        ]

From bf77ff2348549c69d0e26e2fd0ae1cf396a47e48 Mon Sep 17 00:00:00 2001
From: Alan Crosswell <alan@columbia.edu>
Date: Sun, 9 Jun 2019 18:49:26 -0400
Subject: [PATCH 2/4] test case for get_schema_operation_parameters

---
 example/tests/unit/test_openapi.py | 60 ++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 example/tests/unit/test_openapi.py

diff --git a/example/tests/unit/test_openapi.py b/example/tests/unit/test_openapi.py
new file mode 100644
index 00000000..78aa5cd4
--- /dev/null
+++ b/example/tests/unit/test_openapi.py
@@ -0,0 +1,60 @@
+from rest_framework import filters as drf_filters
+from rest_framework_json_api import filters as dja_filters
+from rest_framework_json_api.django_filters import backends
+from example.views import EntryViewSet
+
+
+class DummyEntryViewSet(EntryViewSet):
+    filter_backends = (dja_filters.QueryParameterValidationFilter, dja_filters.OrderingFilter,
+                       backends.DjangoFilterBackend, drf_filters.SearchFilter)
+    filterset_fields = {
+        'id': ('exact',),
+        'headline': ('exact',),
+    }
+
+def test_filters_get_schema_params():
+    """
+    test all my filters for `get_schema_operation_parameters()`
+    """
+    # list of tuples: (filter, expected result)
+    filters = [
+        (dja_filters.QueryParameterValidationFilter, []),
+        (backends.DjangoFilterBackend,
+         [
+             {
+                 'name': 'filter[id]', 'required': False, 'in': 'query',
+                 'description': 'id', 'schema': {'type': 'string'}
+             },
+             {
+                 'name': 'filter[headline]', 'required': False, 'in': 'query',
+                 'description': 'headline', 'schema': {'type': 'string'}
+             }
+          ]
+         ),
+        (dja_filters.OrderingFilter,
+         [
+             {
+                 'name': 'sort', 'required': False, 'in': 'query',
+                 'description': 'Which field to use when ordering the results.',
+                 'schema': {'type': 'string'}
+             }
+         ]
+        ),
+        (drf_filters.SearchFilter,
+         [
+             {
+                 'name': 'filter[search]', 'required': False, 'in': 'query',
+                 'description': 'A search term.',
+                 'schema': {'type': 'string'}
+             }
+         ]
+        ),
+    ]
+    view = DummyEntryViewSet()
+
+    for c, expected in filters:
+        f = c()
+        #  get_schema_operation_parameters is only available in DRF >= 3.10
+        if hasattr(f, 'get_schema_operation_parameters'):
+            result = f.get_schema_operation_parameters(view)
+            assert result == expected

From d400c4ad65d21db8c73c68dd0ccf8e80c15588b0 Mon Sep 17 00:00:00 2001
From: Alan Crosswell <alan@columbia.edu>
Date: Sun, 9 Jun 2019 18:50:00 -0400
Subject: [PATCH 3/4] confusion about view.queryset vs. view.get_queryset()

---
 rest_framework_json_api/django_filters/backends.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/rest_framework_json_api/django_filters/backends.py b/rest_framework_json_api/django_filters/backends.py
index 58ac1a75..3c04baf7 100644
--- a/rest_framework_json_api/django_filters/backends.py
+++ b/rest_framework_json_api/django_filters/backends.py
@@ -152,7 +152,8 @@ def get_schema_operation_parameters(self, view):
         # see https://github.com/carltongibson/django-filter/pull/1086
 
         try:
-            queryset = view.get_queryset()
+            #queryset = view.get_queryset()
+            queryset = view.queryset
         except Exception:
             queryset = None
             warnings.warn(

From c7afeb7af3ff6f689144289ca9791a9d0a5dd9fc Mon Sep 17 00:00:00 2001
From: Alan Crosswell <alan@columbia.edu>
Date: Sun, 9 Jun 2019 18:57:57 -0400
Subject: [PATCH 4/4] flake8

---
 example/tests/unit/test_openapi.py            | 57 +++++++++----------
 .../django_filters/backends.py                |  5 +-
 2 files changed, 28 insertions(+), 34 deletions(-)

diff --git a/example/tests/unit/test_openapi.py b/example/tests/unit/test_openapi.py
index 78aa5cd4..01217eb5 100644
--- a/example/tests/unit/test_openapi.py
+++ b/example/tests/unit/test_openapi.py
@@ -1,6 +1,8 @@
 from rest_framework import filters as drf_filters
+
 from rest_framework_json_api import filters as dja_filters
 from rest_framework_json_api.django_filters import backends
+
 from example.views import EntryViewSet
 
 
@@ -12,6 +14,7 @@ class DummyEntryViewSet(EntryViewSet):
         'headline': ('exact',),
     }
 
+
 def test_filters_get_schema_params():
     """
     test all my filters for `get_schema_operation_parameters()`
@@ -19,36 +22,30 @@ def test_filters_get_schema_params():
     # list of tuples: (filter, expected result)
     filters = [
         (dja_filters.QueryParameterValidationFilter, []),
-        (backends.DjangoFilterBackend,
-         [
-             {
-                 'name': 'filter[id]', 'required': False, 'in': 'query',
-                 'description': 'id', 'schema': {'type': 'string'}
-             },
-             {
-                 'name': 'filter[headline]', 'required': False, 'in': 'query',
-                 'description': 'headline', 'schema': {'type': 'string'}
-             }
-          ]
-         ),
-        (dja_filters.OrderingFilter,
-         [
-             {
-                 'name': 'sort', 'required': False, 'in': 'query',
-                 'description': 'Which field to use when ordering the results.',
-                 'schema': {'type': 'string'}
-             }
-         ]
-        ),
-        (drf_filters.SearchFilter,
-         [
-             {
-                 'name': 'filter[search]', 'required': False, 'in': 'query',
-                 'description': 'A search term.',
-                 'schema': {'type': 'string'}
-             }
-         ]
-        ),
+        (backends.DjangoFilterBackend, [
+            {
+                'name': 'filter[id]', 'required': False, 'in': 'query',
+                'description': 'id', 'schema': {'type': 'string'}
+            },
+            {
+                'name': 'filter[headline]', 'required': False, 'in': 'query',
+                'description': 'headline', 'schema': {'type': 'string'}
+            }
+        ]),
+        (dja_filters.OrderingFilter, [
+            {
+                'name': 'sort', 'required': False, 'in': 'query',
+                'description': 'Which field to use when ordering the results.',
+                'schema': {'type': 'string'}
+            }
+        ]),
+        (drf_filters.SearchFilter, [
+            {
+                'name': 'filter[search]', 'required': False, 'in': 'query',
+                'description': 'A search term.',
+                'schema': {'type': 'string'}
+            }
+        ]),
     ]
     view = DummyEntryViewSet()
 
diff --git a/rest_framework_json_api/django_filters/backends.py b/rest_framework_json_api/django_filters/backends.py
index 3c04baf7..88211831 100644
--- a/rest_framework_json_api/django_filters/backends.py
+++ b/rest_framework_json_api/django_filters/backends.py
@@ -148,11 +148,8 @@ def get_schema_operation_parameters(self, view):
         """
         Return Open API query parameter schema.
         """
-        # TODO: Update this to extend the upstream django-filter implemntation if and when that gets merged.
-        # see https://github.com/carltongibson/django-filter/pull/1086
-
         try:
-            #queryset = view.get_queryset()
+            # queryset = view.get_queryset()
             queryset = view.queryset
         except Exception:
             queryset = None