Renamed and documented 'get_schema_fields' interface.

This commit is contained in:
Tom Christie 2016-10-10 12:51:19 +01:00
parent 18aebbbe01
commit 3f3213b5d0
5 changed files with 57 additions and 32 deletions

View File

@ -416,6 +416,12 @@ Generic filters may also present an interface in the browsable API. To do so you
The method should return a rendered HTML string.
## Pagination & schemas
You can also make the filter controls available to the schema autogeneration
that REST framework provides, by implementing a `get_schema_fields()` method,
which should return a list of `coreapi.Field` instances.
# Third party packages
The following third party packages provide additional filter implementations.

View File

@ -276,6 +276,12 @@ To have your custom pagination class be used by default, use the `DEFAULT_PAGINA
API responses for list endpoints will now include a `Link` header, instead of including the pagination links as part of the body of the response, for example:
## Pagination & schemas
You can also make the pagination controls available to the schema autogeneration
that REST framework provides, by implementing a `get_schema_fields()` method,
which should return a list of `coreapi.Field` instances.
---
![Link Header][link-header]

View File

@ -16,7 +16,7 @@ from django.utils import six
from django.utils.translation import ugettext_lazy as _
from rest_framework.compat import (
crispy_forms, distinct, django_filters, guardian, template_render
coreapi, crispy_forms, distinct, django_filters, guardian, template_render
)
from rest_framework.settings import api_settings
@ -72,7 +72,8 @@ class BaseFilterBackend(object):
"""
raise NotImplementedError(".filter_queryset() must be overridden.")
def get_fields(self, view):
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
return []
@ -131,14 +132,21 @@ class DjangoFilterBackend(BaseFilterBackend):
template = loader.get_template(self.template)
return template_render(template, context)
def get_fields(self, view):
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
filter_class = getattr(view, 'filter_class', None)
if filter_class:
return list(filter_class().filters.keys())
return [
coreapi.Field(name=field_name, required=False, location='query')
for field_name in filter_class().filters.keys()
]
filter_fields = getattr(view, 'filter_fields', None)
if filter_fields:
return filter_fields
return [
coreapi.Field(name=field_name, required=False, location='query')
for field_name in filter_fields
]
return []
@ -231,8 +239,9 @@ class SearchFilter(BaseFilterBackend):
template = loader.get_template(self.template)
return template_render(template, context)
def get_fields(self, view):
return [self.search_param]
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
return [coreapi.Field(name=self.search_param, required=False, location='query')]
class OrderingFilter(BaseFilterBackend):
@ -347,8 +356,9 @@ class OrderingFilter(BaseFilterBackend):
context = self.get_template_context(request, queryset, view)
return template_render(template, context)
def get_fields(self, view):
return [self.ordering_param]
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
return [coreapi.Field(name=self.ordering_param, required=False, location='query')]
class DjangoObjectPermissionsFilter(BaseFilterBackend):

View File

@ -15,7 +15,7 @@ from django.utils import six
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.translation import ugettext_lazy as _
from rest_framework.compat import template_render
from rest_framework.compat import coreapi, template_render
from rest_framework.exceptions import NotFound
from rest_framework.response import Response
from rest_framework.settings import api_settings
@ -157,7 +157,8 @@ class BasePagination(object):
def get_results(self, data):
return data['results']
def get_fields(self, view):
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
return []
@ -283,10 +284,16 @@ class PageNumberPagination(BasePagination):
context = self.get_html_context()
return template_render(template, context)
def get_fields(self, view):
if self.page_size_query_param is None:
return [self.page_query_param]
return [self.page_query_param, self.page_size_query_param]
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
fields = [
coreapi.Field(name=self.page_query_param, required=False, location='query')
]
if self.page_size_query_param is not None:
fields.append([
coreapi.Field(name=self.page_size_query_param, required=False, location='query')
])
return fields
class LimitOffsetPagination(BasePagination):
@ -415,8 +422,12 @@ class LimitOffsetPagination(BasePagination):
context = self.get_html_context()
return template_render(template, context)
def get_fields(self, view):
return [self.limit_query_param, self.offset_query_param]
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
return [
coreapi.Field(name=self.limit_query_param, required=False, location='query'),
coreapi.Field(name=self.offset_query_param, required=False, location='query')
]
class CursorPagination(BasePagination):
@ -721,5 +732,8 @@ class CursorPagination(BasePagination):
context = self.get_html_context()
return template_render(template, context)
def get_fields(self, view):
return [self.cursor_query_param]
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
return [
coreapi.Field(name=self.cursor_query_param, required=False, location='query')
]

View File

@ -42,17 +42,6 @@ def get_pk_name(model):
return _get_pk(meta).name
def as_query_fields(items):
"""
Take a list of Fields and plain strings.
Convert any pain strings into `location='query'` Field instances.
"""
return [
item if isinstance(item, coreapi.Field) else coreapi.Field(name=item, required=False, location='query')
for item in items
]
def is_api_view(callback):
"""
Return `True` if the given view callback is a REST framework view/viewset.
@ -506,7 +495,7 @@ class SchemaGenerator(object):
return []
paginator = view.pagination_class()
return as_query_fields(paginator.get_fields(view))
return paginator.get_schema_fields(view)
def get_filter_fields(self, path, method, view):
if not is_list_view(path, method, view):
@ -517,7 +506,7 @@ class SchemaGenerator(object):
fields = []
for filter_backend in view.filter_backends:
fields += as_query_fields(filter_backend().get_fields(view))
fields += filter_backend().get_schema_fields(view)
return fields
# Method for generating the link layout....