Pergunta

Eu uso render_to_response do Django para retornar um documento XML. Este documento XML especial destina-se a uma biblioteca de gráficos baseado em flash. A biblioteca exige que o documento XML começar com um BOM (byte ordem marcador). Como posso fazer Django prepent o BOM para a resposta?

Ele trabalha para inserir o BOM para o modelo, mas é inconveniente porque Emacs remove-lo cada vez que eu editar o arquivo.

Eu tentei reescrever render_to_response como segue, mas falha porque o BOM está sendo UTF-8 codificado:

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)
Foi útil?

Solução

Você não está realmente falando de um BOM (Byte Order Mark), uma vez que UTF-8 não tem um BOM. Do seu código exemplo, a biblioteca espera que o texto para ter 3 lixo bytes prefixado por alguma razão inexplicável.

Seu código é quase correto, mas você deve preceder os bytes como bytes , não caracteres. Tente isto:

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)

Outras dicas

Esta solução, com base em uma versão anterior da resposta de John Millikin, é mais complexa do que a que eu aceito, mas eu estou incluindo para ficar completo. Primeiro, definir uma classe middleware:

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

Adicione seu nome para MIDDLEWARE_CLASSES em suas configurações. Então render_to_response redefine:

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

Agora, você pode fazer render_to_response("foo.xml", mimetype="text/xml", bom=True) a fim prefixar o BOM para uma resposta particular.

A coisa mais simples poderia ser a de configurar Emacs para não remover o BOM.

Mas render_to_response não é uma função complicada. É basicamente:

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

Você poderia facilmente chamar render_to_string e preceder o BOM.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top