Подготовить спецификацию к XML-ответу от Django
-
07-07-2019 - |
Вопрос
Я использую render_to_response
Джанго для возврата XML-документа. Этот конкретный документ XML предназначен для библиотеки диаграмм на основе флэш-памяти. Библиотека требует, чтобы документ XML начинался с спецификации (маркера порядка байтов). Как я могу заставить Django подготовить спецификацию к ответу?
Он работает для вставки спецификации в шаблон, но это неудобно, потому что Emacs удаляет ее каждый раз, когда я редактирую файл.
Я попытался переписать render_to_response
следующим образом, но это не удалось, потому что спецификация кодируется в UTF-8:
def render_to_response(*args, **kwargs):
bom = kwargs.pop('bom', False)
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
s = django.template.loader.render_to_string(*args, **kwargs)
if bom:
s = u'\xef\xbb\xbf' + s
return HttpResponse(s, **httpresponse_kwargs)
Решение
Вы на самом деле не говорите о спецификации (метке порядка байтов), поскольку в UTF-8 нет спецификации. Исходя из вашего примера кода, библиотека ожидает, что в тексте будет добавлено 3 байта мусора по какой-то необъяснимой причине.
Ваш код почти верен, но вы должны добавлять байты в виде байтов , а не символов. Попробуйте это:
def render_to_response(*args, **kwargs):
bom = kwargs.pop('bom', False)
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
s = django.template.loader.render_to_string(*args, **kwargs)
if bom:
s = '\xef\xbb\xbf' + s.encode("utf-8")
return HttpResponse(s, **httpresponse_kwargs)
Другие советы
Это решение, основанное на предыдущей версии ответа Джона Милликина, является более сложным, чем то, которое я принял, но я привожу его здесь для полноты. Сначала определите класс промежуточного программного обеспечения:
class AddBOMMiddleware(object):
def process_response(self, request, response):
import codecs
if getattr(response, 'bom', False):
response.content = codecs.BOM_UTF8 + response.content
return response
Добавьте его имя в MIDDLEWARE_CLASSES в ваших настройках. Затем переопределите render_to_response
:
def render_to_response(*args, **kwargs):
bom = kwargs.pop('bom', False)
httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
rendered = django.template.loader.render_to_string(*args, **kwargs)
response = django.http.HttpResponse(rendered, **httpresponse_kwargs)
if bom:
response.bom = True
return response
Теперь можно выполнить render_to_response (" foo.xml " ;, mimetype = " text / xml " ;, bom = True)
, чтобы добавить спецификацию к конкретному ответу. р>
Проще всего настроить Emacs так, чтобы он не удалял спецификацию.
Но render_to_response не сложная функция. Это в основном:
def render_to_response(*args, **kwargs):
return HttpResponse(loader.render_to_string(*args, **kwargs))
Вы могли бы легко вызвать render_to_string и добавить к нему спецификацию.