将 BOM 添加到来自 Django 的 XML 响应之前

发布于 2024-08-04 16:00:04 字数 592 浏览 9 评论 0原文

我使用 Django 的 render_to_response 返回 XML 文档。这个特定的 XML 文档适用于基于 Flash 的图表库。该库要求 XML 文档以 BOM(字节顺序标记)开头。如何让 Django 将 BOM 添加到响应中?

将 BOM 插入到模板中是可行的,但这很不方便,因为每次编辑文件时 Emacs 都会将其删除。

我尝试按如下方式重写 render_to_response ,但失败了,因为 BOM 是 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)

I use Django's render_to_response to return an XML document. This particular XML document is intended for a flash-based charting library. The library requires that the XML document start with a BOM (byte order marker). How can I make Django prepent the BOM to 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 have tried to rewrite render_to_response as follows, but it fails because the BOM is being 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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凡间太子 2024-08-11 16:00:04

您实际上并不是在谈论 BOM(字节顺序标记),因为 UTF-8 没有 BOM。从您的示例代码来看,由于某些无法解释的原因,该库期望文本前面添加 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)

You're not really talking about a BOM (Byte Order Mark), since UTF-8 doesn't have a BOM. From your example code, the library expects the text to have 3 garbage bytes prepended for some inexplicable reason.

Your code is almost correct, but you must prepend the bytes as bytes, not characters. Try this:

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)
昇り龍 2024-08-11 16:00:04

该解决方案基于约翰·米利金答案的先前版本,比我接受的解决方案更复杂,但为了完整性我将其包含在此处。首先,定义一个中间件类:

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) 以便将 BOM 添加到特定的反应。

This solution, based on a previous version of John Millikin's answer, is more complex than the one I accepted, but I'm including it here for completeness. First, define a 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 its name to MIDDLEWARE_CLASSES in your settings. Then 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

Now, you can do render_to_response("foo.xml", mimetype="text/xml", bom=True) in order to prepend the BOM to a particular response.

铜锣湾横着走 2024-08-11 16:00:04

最简单的事情可能是将 Emacs 配置为不删除 BOM。

但 render_to_response 并不是一个复杂的函数。基本上是:

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

您可以轻松调用 render_to_string 并在前面添加 BOM。

The simplest thing might be to configure Emacs not to remove the BOM.

But render_to_response is not a complicated function. It's basically:

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

You could easily call render_to_string and prepend the BOM.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文