Handle lazy() proxies in user-supplied objects

master
Cristi Vîjdea 2018-12-21 00:44:05 +02:00 committed by Cristi Vijdea
parent 0c38c30020
commit bbed2acf06
2 changed files with 17 additions and 7 deletions

View File

@ -1,12 +1,16 @@
import six
import collections
import logging import logging
import re import re
from collections import OrderedDict from collections import OrderedDict
from coreapi.compat import urlparse from coreapi.compat import urlparse
from django.urls import get_script_prefix from django.urls import get_script_prefix
from django.utils.functional import Promise
from inflection import camelize from inflection import camelize
from .utils import filter_none from .utils import filter_none, force_real_str
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -128,13 +132,19 @@ class SwaggerDict(OrderedDict):
if id(obj) in memo: if id(obj) in memo:
return memo[id(obj)] 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() result = OrderedDict()
memo[id(obj)] = result memo[id(obj)] = result
for attr, val in obj.items(): for attr, val in obj.items():
result[attr] = SwaggerDict._as_odict(val, memo) result[attr] = SwaggerDict._as_odict(val, memo)
return result 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 type(obj)(SwaggerDict._as_odict(elem, memo) for elem in obj)
return obj return obj

View File

@ -4,7 +4,7 @@ from django.shortcuts import resolve_url
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.functional import Promise from django.utils.functional import Promise
from rest_framework.renderers import BaseRenderer, JSONRenderer, TemplateHTMLRenderer 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 .app_settings import redoc_settings, swagger_settings
from .codecs import VALIDATORS, OpenAPICodecJson, OpenAPICodecYaml from .codecs import VALIDATORS, OpenAPICodecJson, OpenAPICodecYaml
@ -76,7 +76,7 @@ class _UIRenderer(BaseRenderer):
def set_context(self, renderer_context, swagger=None): def set_context(self, renderer_context, swagger=None):
renderer_context['title'] = swagger.info.title or '' if swagger else '' renderer_context['title'] = swagger.info.title or '' if swagger else ''
renderer_context['version'] = swagger.info.version 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['USE_SESSION_AUTH'] = swagger_settings.USE_SESSION_AUTH
renderer_context.update(self.get_auth_urls()) renderer_context.update(self.get_auth_urls())
@ -120,7 +120,7 @@ class SwaggerUIRenderer(_UIRenderer):
def set_context(self, renderer_context, swagger=None): def set_context(self, renderer_context, swagger=None):
super(SwaggerUIRenderer, self).set_context(renderer_context, swagger) 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): def get_swagger_ui_settings(self):
data = { data = {
@ -157,7 +157,7 @@ class ReDocRenderer(_UIRenderer):
def set_context(self, renderer_context, swagger=None): def set_context(self, renderer_context, swagger=None):
super(ReDocRenderer, self).set_context(renderer_context, swagger) 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): def get_redoc_settings(self):
data = { data = {