# -*- coding: utf-8 -*-
"""
###################################################
Django Rest Framework Renderers for the API Browser
###################################################
Renderers and utilities for rendering the API Browser.
"""
from __future__ import print_function
from django.utils import safestring
# from rest_framework import status
from rest_framework import renderers as drf_renderers
from . import config
from . import formatting
from . import highlight
def get_view_name(view_cls, suffix=None):
"""Return the display name for an APIView.
Converts camelcase to space-separated and replaces underscores with spaces.
.. NOTE:: This name is used in the browsable API, and in OPTIONS responses.
Parameters
----------
view_cls
The view class to get the name for.
suffix: str
DEPRECATED?: A suffix to add to the end of the generated name.
``get_view_name`` doesn't seem to ever be called with a suffix
argument in the Django Rest Framework code.
Returns
-------
str
The display name for the view.
"""
name = view_cls.__name__
if name.endswith('View') and name != 'View':
name = name[:-4]
if name.endswith('ViewSet') and name != 'ViewSet':
name = name[:-7]
name = formatting.camelcase_to_space_separated(name)
name = ' '.join(name.split('_'))
if suffix:
name += ' ' + suffix
return name
def get_view_description(view_cls, html=False):
"""Return a textual description of the view parsed as ReStructured Text.
.. NOTE:: This description is used in the browsable API, and in OPTIONS
responses.
"""
description = view_cls.__doc__ or ''
description = formatting.dedent_docstring(description)
if html:
rendered = formatting.restructured_text_to_html(description)
return safestring.mark_safe(rendered['body'])
return description
class APIBrowserRenderer(drf_renderers.BrowsableAPIRenderer):
"""Render for the API Browser (text/html).
The API Browser is similar in concept to the
`Django Rest Framework Browsable API
<http://www.django-rest-framework.org/topics/browsable-api/>`_.
Differences:
- API Browser uses Pygments for code highlighting and linkifying.
- API Browser includes serializer metadata in the documentation.
- API Browser parses docstrings with reStructuredText instead of Markdown.
- (future) API Browser frontend is not based on Bootstrap.
- (future) API Browser outputs metadata as JSON Schema.
"""
media_type = 'text/html'
format = config.get('FORMAT_SUFFIX')
template = config.get('TEMPLATE')
filter_template = config.get('FILTER_TEMPLATE')
form_renderer_class = drf_renderers.HTMLFormRenderer
charset = 'utf-8'
def get_description(self, view, status_code):
"""Get the description for a view.
The DRF version does not display documentation for unauthenticated
users (if the endpoint requires login). This version **does** display
documentation.
"""
if config.get('ALWAYS_DISPLAY_DOCUMENTATION'):
return view.get_view_description(html=True)
if status_code in (status.HTTP_401_UNAUTHORIZED,
status.HTTP_403_FORBIDDEN):
return ''
return view.get_view_description(html=True)
def get_content(self, renderer, data,
accepted_media_type, renderer_context):
"""
Get the content as if it had been rendered by the default
non-documenting renderer.
"""
if not renderer:
return '[No renderers were found]'
renderer_context['indent'] = 4
content = renderer.render(data, accepted_media_type, renderer_context)
render_style = getattr(renderer, 'render_style', 'text')
assert render_style in ['text', 'binary'], 'Expected .render_style ' \
'"text" or "binary", but got "%s"' % render_style
if render_style == 'binary':
return '[%d bytes of binary content]' % len(content)
highlighted_content = highlight.highlight_and_hyperlink_json(content)
return highlighted_content
# return content
def get_context(self, data, accepted_media_type, renderer_context):
context = super(APIBrowserRenderer, self).get_context(
data, accepted_media_type, renderer_context)
view = renderer_context.get('view')
request = renderer_context.get('request')
metadata = view.metadata_class().determine_metadata(request, view)
context['metadata_renders'] = metadata.get('renders')
context['metadata_parses'] = metadata.get('parses')
context['metadata_actions'] = metadata.get('actions')
context['metadata'] = metadata
context['pygments_css'] = highlight.get_styles('trac')
return context