import json from django.utils import six from django.conf import settings from django.views.generic import View from django.utils.safestring import mark_safe from django.utils.encoding import smart_text from django.shortcuts import render_to_response from django.template import RequestContext from django.core.exceptions import PermissionDenied from .compat import import_string from rest_framework.views import Response from rest_framework.settings import api_settings from rest_framework.utils import formatting from rest_framework_swagger.urlparser import UrlParser from rest_framework_swagger.apidocview import APIDocView from rest_framework_swagger.docgenerator import DocumentationGenerator import rest_framework_swagger as rfs try: JSONRenderer = list(filter( lambda item: item.format == 'json', api_settings.DEFAULT_RENDERER_CLASSES, ))[0] except IndexError: from rest_framework.renderers import JSONRenderer def get_restructuredtext(view_cls, html=False): from docutils import core description = view_cls.__doc__ or '' description = formatting.dedent(smart_text(description)) if html: parts = core.publish_parts(source=description, writer_name='html') html = parts['body_pre_docinfo'] + parts['fragment'] return mark_safe(html) return description def get_full_base_path(request): try: base_path = rfs.SWAGGER_SETTINGS['base_path'] except KeyError: return request.build_absolute_uri(request.path).rstrip('/') else: protocol = 'https' if request.is_secure() else 'http' return '{0}://{1}'.format(protocol, base_path.rstrip('/')) class SwaggerUIView(View): def get(self, request, *args, **kwargs): if not self.has_permission(request): return self.handle_permission_denied(request) template_name = rfs.SWAGGER_SETTINGS.get('template_path') data = { 'swagger_settings': { 'discovery_url': "%s/api-docs/" % get_full_base_path(request), 'api_key': rfs.SWAGGER_SETTINGS.get('api_key', ''), 'api_version': rfs.SWAGGER_SETTINGS.get('api_version', ''), 'token_type': rfs.SWAGGER_SETTINGS.get('token_type'), 'enabled_methods': mark_safe( json.dumps(rfs.SWAGGER_SETTINGS.get('enabled_methods'))), 'doc_expansion': rfs.SWAGGER_SETTINGS.get('doc_expansion', ''), }, 'rest_framework_settings': { 'DEFAULT_VERSIONING_CLASS': settings.REST_FRAMEWORK.get('DEFAULT_VERSIONING_CLASS', '') if hasattr(settings, 'REST_FRAMEWORK') else None, }, 'django_settings': { 'CSRF_COOKIE_NAME': mark_safe( json.dumps(getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken'))), } } response = render_to_response( template_name, RequestContext(request, data)) return response def has_permission(self, request): if rfs.SWAGGER_SETTINGS.get('is_superuser') and \ not request.user.is_superuser: return False if rfs.SWAGGER_SETTINGS.get('is_authenticated') and \ not request.user.is_authenticated(): return False return True def handle_permission_denied(self, request): permission_denied_handler = rfs.SWAGGER_SETTINGS.get( 'permission_denied_handler') if isinstance(permission_denied_handler, six.string_types): permission_denied_handler = import_string( permission_denied_handler) if permission_denied_handler: return permission_denied_handler(request) else: raise PermissionDenied() class SwaggerResourcesView(APIDocView): renderer_classes = (JSONRenderer, ) def get(self, request, *args, **kwargs): apis = [{'path': '/' + path} for path in self.get_resources()] return Response({ 'apiVersion': rfs.SWAGGER_SETTINGS.get('api_version', ''), 'swaggerVersion': '1.2', 'basePath': self.get_base_path(), 'apis': apis, 'info': rfs.SWAGGER_SETTINGS.get('info', { 'contact': '', 'description': '', 'license': '', 'licenseUrl': '', 'termsOfServiceUrl': '', 'title': '', }), }) def get_base_path(self): try: base_path = rfs.SWAGGER_SETTINGS['base_path'] except KeyError: return self.request.build_absolute_uri( self.request.path).rstrip('/') else: protocol = 'https' if self.request.is_secure() else 'http' return '{0}://{1}/{2}'.format(protocol, base_path, 'api-docs') def get_resources(self): urlparser = UrlParser() urlconf = getattr(self.request, "urlconf", None) exclude_url_names = rfs.SWAGGER_SETTINGS.get('exclude_url_names') exclude_namespaces = rfs.SWAGGER_SETTINGS.get('exclude_namespaces') apis = urlparser.get_apis(urlconf=urlconf, exclude_url_names=exclude_url_names, exclude_namespaces=exclude_namespaces) authorized_apis = filter(lambda a: self.handle_resource_access(self.request, a['pattern']), apis) authorized_apis_list = list(authorized_apis) resources = urlparser.get_top_level_apis(authorized_apis_list) return resources class SwaggerApiView(APIDocView): renderer_classes = (JSONRenderer, ) def get(self, request, path, *args, **kwargs): apis = self.get_apis_for_resource(path) generator = DocumentationGenerator(for_user=request.user) return Response({ 'apiVersion': rfs.SWAGGER_SETTINGS.get('api_version', ''), 'swaggerVersion': '1.2', 'basePath': self.api_full_uri.rstrip('/'), 'resourcePath': '/' + path, 'apis': generator.generate(apis), 'models': generator.get_models(apis), }) def get_apis_for_resource(self, filter_path): urlparser = UrlParser() urlconf = getattr(self.request, "urlconf", None) exclude_url_names = rfs.SWAGGER_SETTINGS.get('exclude_url_names') exclude_namespaces = rfs.SWAGGER_SETTINGS.get('exclude_namespaces') apis = urlparser.get_apis(urlconf=urlconf, filter_path=filter_path, exclude_url_names=exclude_url_names, exclude_namespaces=exclude_namespaces) authorized_apis = filter(lambda a: self.handle_resource_access(self.request, a['pattern']), apis) authorized_apis_list = list(authorized_apis) return authorized_apis_list