Source code for drf_yasg.renderers

import six

from django.shortcuts import render, resolve_url
from django.utils.functional import Promise
from rest_framework.renderers import BaseRenderer, JSONRenderer, TemplateHTMLRenderer
from rest_framework.utils import json

from .app_settings import redoc_settings, swagger_settings
from .codecs import VALIDATORS, OpenAPICodecJson, OpenAPICodecYaml
from .openapi import Swagger
from .utils import filter_none


class _SpecRenderer(BaseRenderer):
    """Base class for text renderers. Handles encoding and validation."""
    charset = 'utf-8'
    validators = []
    codec_class = None

    @classmethod
    def with_validators(cls, validators):
        assert all(vld in VALIDATORS for vld in validators), "allowed validators are " + ", ".join(VALIDATORS)
        return type(cls.__name__, (cls,), {'validators': validators})

    def render(self, data, media_type=None, renderer_context=None):
        assert self.codec_class, "must override codec_class"
        codec = self.codec_class(self.validators)

        if not isinstance(data, Swagger):  # pragma: no cover
            # if `swagger` is not a ``Swagger`` object, it means we somehow got a non-success ``Response``
            # in that case, it's probably better to let the default ``TemplateHTMLRenderer`` render it
            # see https://github.com/axnsan12/drf-yasg/issues/58
            return JSONRenderer().render(data, media_type, renderer_context)
        return codec.encode(data)


[docs]class OpenAPIRenderer(_SpecRenderer): """Renders the schema as a JSON document with the ``application/openapi+json`` specific mime type.""" media_type = 'application/openapi+json' format = 'openapi' codec_class = OpenAPICodecJson
[docs]class SwaggerJSONRenderer(_SpecRenderer): """Renders the schema as a JSON document with the generic ``application/json`` mime type.""" media_type = 'application/json' format = '.json' codec_class = OpenAPICodecJson
[docs]class SwaggerYAMLRenderer(_SpecRenderer): """Renders the schema as a YAML document.""" media_type = 'application/yaml' format = '.yaml' codec_class = OpenAPICodecYaml
class _UIRenderer(BaseRenderer): """Base class for web UI renderers. Handles loading and passing settings to the appropriate template.""" media_type = 'text/html' charset = 'utf-8' template = '' def render(self, swagger, accepted_media_type=None, renderer_context=None): if not isinstance(swagger, Swagger): # pragma: no cover # if `swagger` is not a ``Swagger`` object, it means we somehow got a non-success ``Response`` # in that case, it's probably better to let the default ``TemplateHTMLRenderer`` render it # see https://github.com/axnsan12/drf-yasg/issues/58 return TemplateHTMLRenderer().render(swagger, accepted_media_type, renderer_context) self.set_context(renderer_context, swagger) return render( renderer_context['request'], self.template, renderer_context ) def set_context(self, renderer_context, swagger): renderer_context['title'] = swagger.info.title renderer_context['version'] = swagger.info.version renderer_context['oauth2_config'] = json.dumps(self.get_oauth2_config()) renderer_context['USE_SESSION_AUTH'] = swagger_settings.USE_SESSION_AUTH renderer_context.update(self.get_auth_urls()) def resolve_url(self, to): if isinstance(to, Promise): to = str(to) if to is None: return None args, kwargs = None, None if not isinstance(to, six.string_types): if len(to) > 2: to, args, kwargs = to elif len(to) == 2: to, kwargs = to args = args or () kwargs = kwargs or {} return resolve_url(to, *args, **kwargs) def get_auth_urls(self): urls = { 'LOGIN_URL': self.resolve_url(swagger_settings.LOGIN_URL), 'LOGOUT_URL': self.resolve_url(swagger_settings.LOGOUT_URL), } return filter_none(urls) def get_oauth2_config(self): data = swagger_settings.OAUTH2_CONFIG assert isinstance(data, dict), "OAUTH2_CONFIG must be a dict" return data
[docs]class SwaggerUIRenderer(_UIRenderer): """Renders a swagger-ui web interface for schema browisng.""" template = 'drf-yasg/swagger-ui.html' format = 'swagger'
[docs] def set_context(self, renderer_context, swagger): super(SwaggerUIRenderer, self).set_context(renderer_context, swagger) renderer_context['swagger_settings'] = json.dumps(self.get_swagger_ui_settings())
[docs] def get_swagger_ui_settings(self): data = { 'url': self.resolve_url(swagger_settings.SPEC_URL), 'operationsSorter': swagger_settings.OPERATIONS_SORTER, 'tagsSorter': swagger_settings.TAGS_SORTER, 'docExpansion': swagger_settings.DOC_EXPANSION, 'deepLinking': swagger_settings.DEEP_LINKING, 'showExtensions': swagger_settings.SHOW_EXTENSIONS, 'defaultModelRendering': swagger_settings.DEFAULT_MODEL_RENDERING, 'defaultModelExpandDepth': swagger_settings.DEFAULT_MODEL_DEPTH, 'defaultModelsExpandDepth': swagger_settings.DEFAULT_MODEL_DEPTH, 'showCommonExtensions': swagger_settings.SHOW_COMMON_EXTENSIONS, 'oauth2RedirectUrl': swagger_settings.OAUTH2_REDIRECT_URL, 'supportedSubmitMethods': swagger_settings.SUPPORTED_SUBMIT_METHODS, 'displayOperationId': swagger_settings.DISPLAY_OPERATION_ID, } data = filter_none(data) if swagger_settings.VALIDATOR_URL != '': data['validatorUrl'] = self.resolve_url(swagger_settings.VALIDATOR_URL) return data
[docs]class ReDocRenderer(_UIRenderer): """Renders a ReDoc web interface for schema browisng.""" template = 'drf-yasg/redoc.html' format = 'redoc'
[docs] def set_context(self, renderer_context, swagger): super(ReDocRenderer, self).set_context(renderer_context, swagger) renderer_context['redoc_settings'] = json.dumps(self.get_redoc_settings())
[docs] def get_redoc_settings(self): data = { 'url': self.resolve_url(redoc_settings.SPEC_URL), 'lazyRendering': redoc_settings.LAZY_RENDERING, 'hideHostname': redoc_settings.HIDE_HOSTNAME, 'expandResponses': redoc_settings.EXPAND_RESPONSES, 'pathInMiddlePanel': redoc_settings.PATH_IN_MIDDLE, 'nativeScrollbars': redoc_settings.NATIVE_SCROLLBARS, 'requiredPropsFirst': redoc_settings.REQUIRED_PROPS_FIRST, } return filter_none(data)
[docs]class ReDocOldRenderer(ReDocRenderer): """Renders a ReDoc 1.x.x web interface for schema browisng.""" template = 'drf-yasg/redoc-old.html'