diff --git a/src/drf_yasg/openapi.py b/src/drf_yasg/openapi.py index a88da60..17716fa 100644 --- a/src/drf_yasg/openapi.py +++ b/src/drf_yasg/openapi.py @@ -1,12 +1,16 @@ +import six + +import collections import logging import re from collections import OrderedDict from coreapi.compat import urlparse from django.urls import get_script_prefix +from django.utils.functional import Promise from inflection import camelize -from .utils import filter_none +from .utils import filter_none, force_real_str logger = logging.getLogger(__name__) @@ -128,13 +132,19 @@ class SwaggerDict(OrderedDict): if id(obj) in memo: return memo[id(obj)] - if isinstance(obj, dict): + if isinstance(obj, Promise) and hasattr(obj, '_proxy____cast'): + # handle __proxy__ objects from django.utils.functional.lazy + obj = obj._proxy____cast() + + if isinstance(obj, collections.Mapping): result = OrderedDict() memo[id(obj)] = result for attr, val in obj.items(): result[attr] = SwaggerDict._as_odict(val, memo) return result - elif isinstance(obj, (list, tuple)): + elif isinstance(obj, six.string_types): + return force_real_str(obj) + elif isinstance(obj, collections.Iterable) and not isinstance(obj, collections.Iterator): return type(obj)(SwaggerDict._as_odict(elem, memo) for elem in obj) return obj diff --git a/src/drf_yasg/renderers.py b/src/drf_yasg/renderers.py index 0369fed..a265688 100644 --- a/src/drf_yasg/renderers.py +++ b/src/drf_yasg/renderers.py @@ -4,7 +4,7 @@ from django.shortcuts import resolve_url from django.template.loader import render_to_string from django.utils.functional import Promise from rest_framework.renderers import BaseRenderer, JSONRenderer, TemplateHTMLRenderer -from rest_framework.utils import json +from rest_framework.utils import encoders, json from .app_settings import redoc_settings, swagger_settings from .codecs import VALIDATORS, OpenAPICodecJson, OpenAPICodecYaml @@ -76,7 +76,7 @@ class _UIRenderer(BaseRenderer): def set_context(self, renderer_context, swagger=None): renderer_context['title'] = swagger.info.title or '' if swagger else '' renderer_context['version'] = swagger.info.version or '' if swagger else '' - renderer_context['oauth2_config'] = json.dumps(self.get_oauth2_config()) + renderer_context['oauth2_config'] = json.dumps(self.get_oauth2_config(), cls=encoders.JSONEncoder) renderer_context['USE_SESSION_AUTH'] = swagger_settings.USE_SESSION_AUTH renderer_context.update(self.get_auth_urls()) @@ -120,7 +120,7 @@ class SwaggerUIRenderer(_UIRenderer): def set_context(self, renderer_context, swagger=None): super(SwaggerUIRenderer, self).set_context(renderer_context, swagger) - renderer_context['swagger_settings'] = json.dumps(self.get_swagger_ui_settings()) + renderer_context['swagger_settings'] = json.dumps(self.get_swagger_ui_settings(), cls=encoders.JSONEncoder) def get_swagger_ui_settings(self): data = { @@ -157,7 +157,7 @@ class ReDocRenderer(_UIRenderer): def set_context(self, renderer_context, swagger=None): super(ReDocRenderer, self).set_context(renderer_context, swagger) - renderer_context['redoc_settings'] = json.dumps(self.get_redoc_settings()) + renderer_context['redoc_settings'] = json.dumps(self.get_redoc_settings(), cls=encoders.JSONEncoder) def get_redoc_settings(self): data = {