Pregunta

Utilizo el render_to_response de Django para devolver un documento XML. Este documento XML en particular está destinado a una biblioteca de gráficos basada en flash. La biblioteca requiere que el documento XML comience con una lista de materiales (marcador de orden de bytes). ¿Cómo puedo hacer que Django prepete la lista de materiales para la respuesta?

Funciona para insertar la lista de materiales en la plantilla, pero es inconveniente porque Emacs la elimina cada vez que edito el archivo.

He intentado reescribir render_to_response de la siguiente manera, pero falla porque la lista de materiales está siendo codificada en 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)
¿Fue útil?

Solución

Realmente no estás hablando de una BOM (marca de orden de bytes), ya que UTF-8 no tiene una BOM. De su código de ejemplo, la biblioteca espera que el texto tenga 3 bytes de basura antepuestos por alguna razón inexplicable.

Su código es casi correcto, pero debe anteponer los bytes como bytes , no caracteres. Prueba esto:

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)

Otros consejos

Esta solución, basada en una versión anterior de la respuesta de John Millikin, es más compleja que la que acepté, pero la incluyo aquí para completarla. Primero, defina una clase de 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

Agregue su nombre a MIDDLEWARE_CLASSES en su configuración. Luego redefine 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

Ahora, puede hacer render_to_response (" foo.xml " ;, mimetype = " text / xml " ;, bom = True) para anteponer la lista de materiales a una respuesta particular.

Lo más simple podría ser configurar Emacs para que no elimine la lista de materiales.

Pero render_to_response no es una función complicada. Básicamente es:

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

Puede llamar fácilmente render_to_string y anteponer la lista de materiales.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top