Skip to content

Instantly share code, notes, and snippets.

@alexryabtsev
Last active August 15, 2016 07:53
Show Gist options
  • Select an option

  • Save alexryabtsev/abfcbcb786ff8cab92bb1101ddc570de to your computer and use it in GitHub Desktop.

Select an option

Save alexryabtsev/abfcbcb786ff8cab92bb1101ddc570de to your computer and use it in GitHub Desktop.
Extend Django REST Swagger with additional request params
import collections
from django.conf import settings
from rest_framework import fields
from rest_framework.settings import api_settings
field_to_yaml_type = collections.defaultdict(
lambda: 'string',
{
fields.IntegerField: 'integer',
fields.FloatField: 'number',
fields.BooleanField: 'boolean',
fields.NullBooleanField: 'boolean',
}
)
# Based on http://stackoverflow.com/a/37809954
def add_input_query_parameters(
serializer_class, add_pagination=False, default_limit=None, skip_offset=False): # pragma: no cover
"""
Decorator to add info about input serializer to Swagger documentation
:param serializer_class: input serializer class
:param add_pagination: add pagination fields
:param default_limit: default limit
:param skip_offset: skip offset parameter in docs
:return:
"""
def decorator(method):
def wrapper(*args, **kwargs):
return method(*args, **kwargs)
import yaml
from rest_framework_swagger.introspectors import IntrospectorHelper, BaseViewIntrospector
i = BaseViewIntrospector(None, None, None, None)
parser = i.get_yaml_parser()
plain_text_doc = IntrospectorHelper.strip_yaml_from_docstring(method.__doc__)
yaml_object = parser.load_obj_from_docstring(method.__doc__) or {}
if 'parameters' in yaml_object:
if not isinstance(yaml_object['parameters'], list):
raise ValueError('parameters in YAML docstring should be a list instance')
else:
yaml_object['parameters'] = list()
serializer = serializer_class()
for field_name, field in serializer.fields.items():
parameter = {
'name': field_name,
'description': field.help_text,
'type': field_to_yaml_type[type(field)],
'required': field.required,
'paramType': 'query',
}
yaml_object['parameters'].append(parameter)
if add_pagination:
assert api_settings.DEFAULT_PAGINATION_CLASS
assert api_settings.DEFAULT_PAGINATION_CLASS.limit_query_param
assert api_settings.DEFAULT_PAGINATION_CLASS.offset_query_param
assert api_settings.PAGE_SIZE
yaml_object['parameters'].append({
'name': api_settings.DEFAULT_PAGINATION_CLASS.limit_query_param,
'description': 'page size, default: {}'.format(default_limit or api_settings.PAGE_SIZE),
'type': 'integer',
'required': False,
'paramType': 'query',
})
if not skip_offset:
yaml_object['parameters'].append({
'name': api_settings.DEFAULT_PAGINATION_CLASS.offset_query_param,
'description': 'offset of elements, default: 0',
'type': 'integer',
'required': False,
'paramType': 'query',
})
wrapper.__doc__ = '\n'.join([plain_text_doc, '---', yaml.dump(yaml_object, default_flow_style=False)])
return wrapper
return decorator
class FooLogListAPIView(ListAPIView):
"""
API call to get list of Foo.
"""
serializer_class = FooListSerializer
input_serializer_class = InputFooSerializer # custom logic for input parameters
queryset = Foo.objects.all()
@add_input_query_parameters(InputFooSerializer, add_pagination=True)
def get(self, request, *args, **kwargs):
"""
---
response_serializer: foo.serializers.FooListSerializer
"""
return super(FooLogListAPIView, self).get(request, *args, **kwargs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment