Xml 在django制作的rss提要中插入未转义的html

Xml 在django制作的rss提要中插入未转义的html,xml,django,rss,escaping,feed,Xml,Django,Rss,Escaping,Feed,我正在尝试使用django创建一个podcast rss提要,使用 作为一个提要生成器,它的工作原理是:将信息放入适当的xml标记中 它工作得很好,只是我不想逃避所有的html 特别是,我希望rss提要的值如下所示: 按照 如果在普通视图中呈现html,则可以在html模板中使用。我现在需要类似的东西,以选择性地防止![CDATA[…] 然而,Django似乎“Django自动转义RSS提要(或任何XML)中的特殊字符,不管您是否通过安全过滤器”(请参阅) 目前没有运气: 因此,到目前为止,尝

我正在尝试使用django创建一个podcast rss提要,使用 作为一个提要生成器,它的工作原理是:将信息放入适当的xml标记中

它工作得很好,只是我不想逃避所有的html

特别是,我希望rss提要的
值如下所示:
按照

如果在普通视图中呈现html,则可以在html模板中使用。我现在需要类似的东西,以选择性地防止
![CDATA[…]

然而,Django似乎“Django自动转义RSS提要(或任何XML)中的特殊字符,不管您是否通过安全过滤器”(请参阅)

目前没有运气:

因此,到目前为止,尝试使用已证明是徒劳的

我还不确定如何解释将“autoescape=False传递给django.contrib.syndication.feeds中的render()调用”

向addQuickElement注释中添加
、escape=False
的建议返回了一个错误

 handler.addQuickElement(u'itunes:summary',item['summary'], escape=False)
 TypeError: addQuickElement() got an unexpected keyword argument 'escape'
这是一个问题,但到目前为止我找不到任何解决办法

任何人都知道一种让
出现在最终提要中的简洁方法,而不是逃到
![CDATA[…


编辑: 以下是我发布此问题时的当前格式代码(我还没有尝试合并@Lego的答案)

导入模拟类型
从django.conf导入设置
从django.contrib.syndication.views导入提要
#用于自定义提要
从django.utils.feedgenerator导入Rss201rev2Feed
从django.utils导入feedgenerator
#另见https://github.com/blancltd/blanc-basic-podcast/blob/master/blanc_basic_podcast/podcast/itunesfeed.py
#及https://github.com/aneumeier/feeds/blob/master/feeds/rss.py
#及https://github.com/blancltd/blanc-basic-podcast/blob/master/blanc_basic_podcast/podcast/feeds.py
#及https://docs.djangoproject.com/en/1.7/ref/contrib/syndication/#custom-馈电发生器
从django.contrib.auth.models导入用户
从django.shortcuts导入获取对象或404
从django.utils.translation导入ugettext\u lazy作为_
从django.contrib.sites.models导入站点
从audiotracks.models导入获取曲目、播放列表
Track=get\u Track\u model()
ITEMS_PER_FEED=getattr(设置“AUDIOTRACKS_PODCAST_LIMIT”,99)
#MarkAdded@ToDo重新访问每个提要的默认最大曲目数
从django.core.urlResolver导入反向,反向
从django_slack导入slack_消息
######################################################################
#####尝试从中调整代码https://github.com/CaptainHayashi/django-lass-uryplayer/blob/master/uryplayer/feeds.py
从django.utils.feedgenerator导入Rss201rev2Feed
从django.contrib.syndication.views导入提要
从django.contrib.sites.models导入站点
从django.db.models导入permalink
#从uryplayer.models导入播客
导入日期时间

#MarkAdded试图取消转义因此,根据文档
处理程序
是一个
XMLGenerator
,调用
addQuickElement
假设所有内容都是字符数据。因此,为什么要转义它

您可能需要做的是覆盖SyndicationFeed。添加项目元素(self、handler、item)
并使用
addQuickElement
插入
a
元素,使用添加
itunes:summary
标记


这可能不是100%的功能,但应该可以让您非常接近。

我在Django 1.10中遇到了同样的问题,并将其追溯到所有转义发生的地方。
Django.utils.RssFeed.write()
使用
django.utils.xmlutils.SimplerXMLGenerator
作为处理程序写入项。此处理程序源自
xml.sax.saxutils.XMLGenerator
,它具有一个转义所有内容的
字符方法。因此,要取消转义放入提要中的所有内容,请首先重写xml处理程序:

from django.utils.xmlutils import SimplerXMLGenerator
class UnescapedXMLGenerator(SimplerXMLGenerator):
    def characters(self, content):
        """
        code is mainly copy-paste from Django 1.10 SimplerXMLGenerator.characters
        """
        if content and re.search(r'[\x00-\x08\x0B-\x0C\x0E-\x1F]', content):
            # Fail loudly when content has control chars (unsupported in XML 1.0)
            # See http://www.w3.org/International/questions/qa-controls
            raise UnserializableContentError("Control characters are not supported in XML 1.0")

        # next part from sax.saxutils.XMLGenerator, but without escaping
        if not isinstance(content, unicode):
            content = unicode(content, self._encoding)
        self._write(content)
下一步是重写提要的write方法以使用新的处理程序。以下是Rss2.01提要示例:

from django.utils import feedgenerator
class Rss201rev2FeedUnescaped(feedgenerator.Rss201rev2Feed):
    """
    Rss 2.01 Feed that doesn't escape content
    """
    def write(self, outfile, encoding):
        """
        code is mainly copy-paste from django.utils.feedgenerator.Rss201rev2Feed
        except that the handler is set to UnescapedXMLGenerator
        """
        handler = UnescapedXMLGenerator(outfile, encoding)
        handler.startDocument()
        handler.startElement("rss", self.rss_attributes())
        handler.startElement("channel", self.root_attributes())
        self.add_root_elements(handler)
        self.write_items(handler)
        self.endChannelElement(handler)
        handler.endElement("rss")

下面是我如何在不转义CDATA标记的情况下将其获取到输出中的方法。我创建了AppleGenerator,该程序继承了Rss20rev2Feed默认使用的SimplerXMLGenerator。然后,我使用Rss201rev2feed的写入函数来重写我创建的新AppleGenerator。然后,对于AppleGenerator,我重写了字符和addQuickElement函数,以获取可选输入,从而在需要时禁用转义

from django.utils.xmlutils import SimplerXMLGenerator
from xml.sax.saxutils import escape

class AppleGenerator(SimplerXMLGenerator):
    def addQuickElement(self, name, contents=None, attrs=None, escape_char=True):
        "Convenience method for adding an element with no children"
        if attrs is None: attrs = {}
        self.startElement(name, attrs)
        if contents is not None:
            self.characters(contents, escape_char=escape_char)
        self.endElement(name)

    def characters(self, content, escape_char=True):
        if content:
            self._finish_pending_start_element()
            if not isinstance(content, str):
                content = str(content, self._encoding)
            if escape_char:
                self._write(escape(content))
            else:
                self._write(content)

class ApplePodcastsFeedGenerator(Rss201rev2Feed):
    def write(self, outfile, encoding):
        handler = AppleGenerator(outfile, encoding)
        handler.startDocument()
        handler.startElement("rss", self.rss_attributes())
        handler.startElement("channel", self.root_attributes())
        self.add_root_elements(handler)
        self.write_items(handler)
        self.endChannelElement(handler)
        handler.endElement("rss")
覆盖基本上与函数之前所做的完全相同,但添加了一种不转义它们的方法。以下是SAXUTIL的源代码:

以下是django SimplerXMLGenerator的源代码:

您可以替换代码:

    contents = '<![CDATA[ contents ]]'
    xml.addQuickElement('element', contents=contents)

contents='你能为你的视图添加更多的代码吗?我以前没有使用过django RSS,但我可能会提供一些帮助。非常感谢。当然,我会编辑上面的大量代码转储。我基本上只是复制并调整了它,以适应models.py的变量名。我已经定义了“Playlist”(就像一个有提要的播客系列)和它的“跟踪”模型(“播客”剧集)项目的方向是正确的!只需使用你的代码,我就可以获得50%的成功,<没有为网站转义标记“我将如何”覆盖SyndicationFeed。添加项目元素(self、handler、item)要改变这一点吗?我已经尝试制作自己的自定义RssFeed(SyndicationFeed),重新编写add_root_elements方法,但仍然没有成功,尽管我尝试应用了各种各样的mark_safe()、unescape(…)和html_decode()函数,这些函数的灵感来自于SO…仍然无法停止“handler.ignorablewitspace()执行您描述的操作,不需要重写处理程序。这与handler.characters()相同,但在写入时没有转义。
from django.utils.xmlutils import SimplerXMLGenerator
from xml.sax.saxutils import escape

class AppleGenerator(SimplerXMLGenerator):
    def addQuickElement(self, name, contents=None, attrs=None, escape_char=True):
        "Convenience method for adding an element with no children"
        if attrs is None: attrs = {}
        self.startElement(name, attrs)
        if contents is not None:
            self.characters(contents, escape_char=escape_char)
        self.endElement(name)

    def characters(self, content, escape_char=True):
        if content:
            self._finish_pending_start_element()
            if not isinstance(content, str):
                content = str(content, self._encoding)
            if escape_char:
                self._write(escape(content))
            else:
                self._write(content)

class ApplePodcastsFeedGenerator(Rss201rev2Feed):
    def write(self, outfile, encoding):
        handler = AppleGenerator(outfile, encoding)
        handler.startDocument()
        handler.startElement("rss", self.rss_attributes())
        handler.startElement("channel", self.root_attributes())
        self.add_root_elements(handler)
        self.write_items(handler)
        self.endChannelElement(handler)
        handler.endElement("rss")
    contents = '<![CDATA[ contents ]]'
    xml.addQuickElement('element', contents=contents)
    contents = 'contents'
    xml.startElement('element', {})
    xml._write(f'<![CDATA[ {contents} ]]')
    xml.endElement('element')