Разобрался, поковырявшись в исходниках и доках.
Экранирование производится во время вызова json.dumps внутри JSONRenderer.
Решена проблема была через создание своего Renderer-а на базе JSONRenderer, который может как сериализировать объекты, так и отдавать строку как есть.
Получившийся код рендерера запостил
на codepad
Фактически, была лишь добавлена переменная requires_serializing (True по-умолчанию) и заменен блок
ret = json.dumps(
data, cls=self.encoder_class,
indent=indent, ensure_ascii=self.ensure_ascii,
separators=separators
)
на
if self.requires_serializing is True:
ret = json.dumps(
data, cls=self.encoder_class,
indent=indent, ensure_ascii=self.ensure_ascii,
separators=separators
)
elif type(data) is str:
ret = data
else:
raise TypeError('JSONStringPassRenderer::render \
-> requires_serializing field set to FALSE, but passed @data argument type is not a string')
Полученный рендерер устанавливаем во вью, в котором хотим его использовать (я не питонист вообще ни разу, может быть если лучший способ передать свой рендерер, но так работает)
class CustomJSONView(ApiView):
special_renderer = JSONStringPassRenderer
renderer_classes = (special_renderer, BrowsableAPIRenderer)
Теперь при стандартном инстанцировании объект ведет себя точно так же, как JSONRenderer, а если указать
перед return Response(...)self.special_renderer.requires_serializing = False
и передать строку, то рендерер просто отправит строку как есть (разумеется, без вообще какой-либо валидации)