Подготовить спецификацию к XML-ответу от Django - PullRequest
2 голосов
/ 15 сентября 2009

Я использую Django 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)

Ответы [ 3 ]

2 голосов
/ 15 сентября 2009

Вы на самом деле не говорите о спецификации (метке порядка байтов), так как 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)
1 голос
/ 15 сентября 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), чтобы добавить спецификацию к конкретному ответу.

0 голосов
/ 15 сентября 2009

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

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

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

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

...