Xml 在django制作的rss提要中插入未转义的html
我正在尝试使用django创建一个podcast rss提要,使用 作为一个提要生成器,它的工作原理是:将信息放入适当的xml标记中 它工作得很好,只是我不想逃避所有的html 特别是,我希望rss提要的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)中的特殊字符,不管您是否通过安全过滤器”(请参阅) 目前没有运气: 因此,到目前为止,尝
值如下所示:
按照
如果在普通视图中呈现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')