Prepare BOM for Django XML Response
I am using Django render_to_response
to return an XML document. This particular XML document is for the flash diagram library. The library requires the XML document to start with a BOM (byte byte marker). How can I make Django prefix the BOM for the response?
It works to insert the BOM into the template, but it's inconvenient because Emacs removes it every time I edit the file.
I tried to rewrite render_to_response
as follows, but it fails as the BOM is UTF-8 encoded:
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)
source to share
You are not really talking about BOM (byte) as UTF-8 has no BOM. From your example code, the library expects there to be 3 bytes of garbage in the text, preceded by some unexplained reason.
Your code is almost correct, but you have to add bytes as bytes, not characters. Try the following:
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)
source to share
This solution, based on a previous version of John Millikin's answer, is more complex than the one I accepted, but I am including it here for completeness. First, define your middleware class:
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
Add your name to MIDDLEWARE_CLASSES to your settings. Then override 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
Now you can do render_to_response("foo.xml", mimetype="text/xml", bom=True)
to add a BOM to a specific answer.
source to share
The simplest thing might be to configure Emacs to not remove the spec.
But render_to_response is not a complex function. These are basically:
def render_to_response(*args, **kwargs):
return HttpResponse(loader.render_to_string(*args, **kwargs))
You can call render_to_string easily and add a BOM.
source to share