diff --git a/example/tests/unit/test_openapi.py b/example/tests/unit/test_openapi.py new file mode 100644 index 00000000..01217eb5 --- /dev/null +++ b/example/tests/unit/test_openapi.py @@ -0,0 +1,57 @@ +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 diff --git a/rest_framework_json_api/django_filters/backends.py b/rest_framework_json_api/django_filters/backends.py index 347acb58..88211831 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,29 @@ 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. + """ + try: + # queryset = view.get_queryset() + queryset = view.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() + ]