Подготовить ответ BOM к XML от Django

Я использую Django render_to_response для возврата XML-документа. Этот конкретный XML-документ предназначен для библиотеки диаграмм на основе флэш-памяти. Библиотека требует, чтобы XML-документ начинался с BOM (маркер порядка байтов). Как я могу заставить 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)

person Vebjorn Ljosa    schedule 14.09.2009    source источник


Ответы (3)


На самом деле вы не говорите о спецификации (знак порядка байтов), поскольку в 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)
person John Millikin    schedule 14.09.2009
comment
Я бы предположил, что мы говорим это UTF-8. Некоторое программное обеспечение (как правило, созданное Microsoft) любит помещать спецификации в UTF-8, несмотря на то, что это бессмысленно и вредно. Однако программа чтения XML, для которой она требуется, сломана и вообще не является программой чтения XML. - person bobince; 15.09.2009
comment
В UTF-8 нет такой вещи, как спецификация, потому что в UTF-8 нет порядка байтов. Если какое-то программное обеспечение зависит от случайных мусорных байтов, присутствующих в файле, это нечто другое. - person John Millikin; 15.09.2009
comment
@Vebjorn: я обновил ответ, чтобы отразить ваш отредактированный вопрос. Ваш код уже почти правильный. - person John Millikin; 15.09.2009

Это решение, основанное на предыдущей версии ответа Джона Милликина, более сложное, чем то, которое я принял, но я включаю его сюда для полноты картины. Сначала определите класс промежуточного программного обеспечения:

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), чтобы добавить спецификацию к конкретному ответу.

person Vebjorn Ljosa    schedule 14.09.2009

Самое простое — настроить Emacs так, чтобы спецификация не удалялась.

Но render_to_response — не сложная функция. Это в основном:

def render_to_response(*args, **kwargs):
    return HttpResponse(loader.render_to_string(*args, **kwargs))

Вы можете легко вызвать render_to_string и добавить спецификацию.

person Ned Batchelder    schedule 14.09.2009