Django参考文档:Feed 聚合框架
创始人
2026-04-29 14:25:08
0

Feed 聚合框架

Django 提供了一个高级的 feed 聚合生成框架来创建 RSSAtom feed。

要创建任何聚合 feed,你只需要写一个简短的 Python 类。你可以创建任何你想要的 feed。

Django 还提供了一个低级别的 feed 生成 API。如果你想在网络内容之外或以其他较低级别的方式生成 feed,可以使用这个 API。

高级框架

概况

高级 feed 生成框架由 Feed 类提供。要创建一个 feed,需要写一个 Feed 类,并在你的 URLconf 中指向它的一个实例。

Feed

Feed 类是一个 Python 类,它表示一个聚合 feed。Feed 可以是简单的(例如,一个“站点新闻”feed,或者一个显示博客最新条目的基本 feed),也可以是更复杂的(例如,一个显示特定类别中所有博客条目的 feed,其中类别是可变的)。

Feed 类子类 django.contrib.syndication.views.Feed。它们可以存在于你代码库的任何地方。

Feed 类的实例是可以在你的 URLconf 中使用的视图。

一个简单的例子

这个简单的例子,取自于一个假设的警拍新闻网站,描述了一个最新的五个新闻项目的 feed:

from django.contrib.syndication.views import Feed
from django.urls import reverse
from policebeat.models import NewsItem

class LatestEntriesFeed(Feed):
    title = "Police beat site news"
    link = "/sitenews/"
    description = "Updates on changes and additions to police beat central."

    def items(self):
        return NewsItem.objects.order_by("-pub_date")[:5]

    def item_title(self, item):
        return item.title

    def item_description(self, item):
        return item.description

    # item_link is only needed if NewsItem has no get_absolute_url method.
    def item_link(self, item):
        return reverse("news-item", args=[item.pk])

要连接到这个 feed 的 URL,在你的 URLconf 中放入一个 Feed 对象的实例。例如:

from django.urls import path
from myproject.feeds import LatestEntriesFeed

urlpatterns = [
    # ...
    path("latest/feed/", LatestEntriesFeed()),
    # ...
]

注意:

  • Feed 类的子类 django.contrib.syndication.views.Feed

  • titlelinkdescription 分别对应标准的 RSS </span></code>、<code><span><link></span></code> 和 <code><span><description></span></code> 元素。</p></li> <li><p><code><span>items()</span></code> 是一个返回一个应该作为 <code><span><item></span></code> 元素包含在 feed 中的对象列表的方法。虽然这个例子使用 Django 的 <a><span>对象关系映射器</span></a> 返回 <code><span>NewsItem</span></code> 对象,但是 <code><span>items()</span></code> 并不是一定要返回模型实例。虽然你通过使用Django模型得到了一些“免费”的功能,但 <code><span>items()</span></code> 可以返回任何类型的对象。</p></li> <li><p>如果你正在创建一个 Atom feed,而不是 RSS feed,请设置 <code><span>subtitle</span></code> 属性而不是 <code><span>description</span></code> 属性。参见后面的 <a>同时发布 Atom 和 RSS feeds</a> 的例子。</p></li> </ul> <p>还剩下一件事要做。在一个 RSS Feed 中,每个 <code><span><item></span></code> 都有一个 <code><span><title></span></code>、<code><span><link></span></code> 和 <code><span><description></span></code>。我们需要告诉框架在这些元素中放入哪些数据。</p> <ul> <li><p>对于 <code><span><title></span></code> 和 <code><span><description></span></code> 的内容,Django 尝试在 <a><code><span>Feed</span></code></a> 类上调用方法 <code><span>item_title()</span></code> 和 <code><span>item_description()</span></code>。它们会传递一个单一的参数 <code><span>item</span></code>,也就是对象本身。这些参数是可选的;默认情况下,两者都使用对象的字符串表示。</p> <p>如果你想对标题或描述进行特定格式化,可以使用 <a><span>Django 模板</span></a> 来代替。它们的路径可以通过 <a><code><span>Feed</span></code></a> 类中的 <code><span>title_template</span></code> 和 <code><span>description_template</span></code> 属性来指定。每个项目的模板都会被渲染,并传递两个模板上下文变量。</p> <ul> <li><p><code><span>{{</span> <span>obj</span> <span>}}</span></code>——当前对象(你在 <code><span>items()</span></code> 中返回的对象之一)。</p></li> <li><p><code><span>{{</span> <span>site</span> <span>}}</span></code> —— 代表当前站点的 <a><code><span>django.contrib.sites.models.Site</span></code></a> 对象。这对于 <code><span>{</span> <span>site.domain</span> <span>}}</span></code> 或 <code><span>{</span> <span>site.name</span> <span>}}</span></code> 是很有用的。如果你没有安装 Django 站点框架,那么这个对象将被设置为一个 <a><code><span>RequestSite</span></code></a> 对象。更多内容请参考 <a><span>网站框架文档中的 RequestSite 部分</span></a>。</p></li> </ul> <p>请看下面使用描述模板的 <a>一个复杂的例子</a> 。</p> <dl> <dt> <span><span>Feed.</span></span><span><span>get_context_data</span></span>(<em><span><span>**</span></span><span><span>kwargs</span></span></em>)</dt> <dd><p>如果你需要提供比前面提到的两个变量更多的信息,还有一种方法可以向标题和描述模板传递额外的信息。你可以在你的 <code><span>Feed</span></code> 子类中提供 <code><span>get_context_data</span></code> 方法的实现。例如:</p> <div><div><pre><span></span><span>from</span><span> </span><span>mysite.models</span><span> </span><span>import</span> <span>Article</span> <span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>class</span><span> </span><span>ArticlesFeed</span><span>(</span><span>Feed</span><span>):</span> <span>title</span> <span>=</span> <span>"My articles"</span> <span>description_template</span> <span>=</span> <span>"feeds/articles.html"</span> <span>def</span><span> </span><span>items</span><span>(</span><span>self</span><span>):</span> <span>return</span> <span>Article</span><span>.</span><span>objects</span><span>.</span><span>order_by</span><span>(</span><span>"-pub_date"</span><span>)[:</span><span>5</span><span>]</span> <span>def</span><span> </span><span>get_context_data</span><span>(</span><span>self</span><span>,</span> <span>**</span><span>kwargs</span><span>):</span> <span>context</span> <span>=</span> <span>super</span><span>()</span><span>.</span><span>get_context_data</span><span>(</span><span>**</span><span>kwargs</span><span>)</span> <span>context</span><span>[</span><span>"foo"</span><span>]</span> <span>=</span> <span>"bar"</span> <span>return</span> <span>context</span> </pre></div> </div> </dd></dl> <p>还有模板:</p> <div><div><pre><span></span>Something about <span>{{</span> <span>foo</span> <span>}}</span>: <span>{{</span> <span>obj.description</span> <span>}}</span> </pre></div> </div> <p>本方法将对 <code><span>items()</span></code> 返回的列表中的每个项目调用一次,其关键字参数如下:</p> <ul> <li><p><code><span>item</span></code>:当前项目。出于向后兼容的原因,这个上下文变量的名称是 <code><span>{{</span> <span>obj</span> <span>}}</span></code>。</p></li> <li><p><code><span>obj</span></code>:由 <code><span>get_object()</span></code> 返回的对象。默认情况下,它不会暴露在模板中,以避免与 <code><span>{{</span> <span>obj</span> <span>}}</span></code> 混淆(见上文),但你可以在实现 <code><span>get_context_data()</span></code> 时使用它。</p></li> <li><p><code><span>site</span></code>:如上所述的当前站点。</p></li> <li><p><code><span>request</span></code>:当前请求。</p></li> </ul> <p><code><span>get_context_data()</span></code> 的行为模仿 <a><span>通用视图</span></a>——你应该调用 <code><span>super()</span></code> 从父类中获取上下文数据,添加你的数据并返回修改后的字典。</p> </li> <li><p>要指定 <code><span><link></span></code> 的内容,你有两个选择。对于 <code><span>items()</span></code> 中的每一个项目,Django 首先尝试调用 <a><code><span>Feed</span></code></a> 类上的 <code><span>item_link()</span></code> 方法。以类似于标题和描述的方式,给它传递一个单一的参数,<code><span>item</span></code>。如果该方法不存在,Django 会尝试在该对象上执行一个 <code><span>get_absolute_url()</span></code> 方法。<code><span>get_absolute_url()</span></code> 和 <code><span>item_link()</span></code> 都应该以普通 Python 字符串的形式返回项目的 URL。和 <code><span>get_absolute_url()</span></code> 一样,<code><span>item_link()</span></code> 的结果将直接包含在 URL 中,所以你要负责在方法本身内部进行所有必要的 URL 引用和 ASCII 转换。</p></li> </ul> </section> <section> <span></span><h3>一个复杂的例子</h3> <p>该框架还支持更复杂的 feed,通过参数。</p> <p>例如,一个网站可以为一个城市的每一个警察局提供最近发生的犯罪行为的 RSS feed。如果为每个警察巡逻创建一个单独的 <a><code><span>Feed</span></code></a> 类,那就太傻了;那会违反 <a><span>DRY 原则</span></a>,并且会把数据和编程逻辑联系起来。相反,聚合框架让你访问从你的 <a><span>URLconf</span></a> 传递的参数,这样 feed 就可以根据 URL 中的信息输出项目。</p> <p>可以通过这样的网址访问警察局 feed:</p> <ul> <li><p><code><span>/beats/613/rss/</span></code> -- 返回区域 613 的最近犯罪信息。</p></li> <li><p><code><span>/beats/1424/rss/</span></code> -- 返回区域 1424 的最近犯罪信息。</p></li> </ul> <p>这些可以用 <a><span>URLconf</span></a> 行来匹配,如:</p> <div><div><pre><span></span><span>path</span><span>(</span><span>"beats/<int:beat_id>/rss/"</span><span>,</span> <span>BeatFeed</span><span>()),</span> </pre></div> </div> <p>像视图一样,URL 中的参数和请求对象一起传递给 <code><span>get_object()</span></code> 方法。</p> <p>以下是这些特定警察局 feed 的代码:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>class</span><span> </span><span>BeatFeed</span><span>(</span><span>Feed</span><span>):</span> <span>description_template</span> <span>=</span> <span>"feeds/beat_description.html"</span> <span>def</span><span> </span><span>get_object</span><span>(</span><span>self</span><span>,</span> <span>request</span><span>,</span> <span>beat_id</span><span>):</span> <span>return</span> <span>Beat</span><span>.</span><span>objects</span><span>.</span><span>get</span><span>(</span><span>pk</span><span>=</span><span>beat_id</span><span>)</span> <span>def</span><span> </span><span>title</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span>return</span> <span>"Police beat central: Crimes for beat </span><span>%s</span><span>"</span> <span>%</span> <span>obj</span><span>.</span><span>beat</span> <span>def</span><span> </span><span>link</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span>return</span> <span>obj</span><span>.</span><span>get_absolute_url</span><span>()</span> <span>def</span><span> </span><span>description</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span>return</span> <span>"Crimes recently reported in police beat </span><span>%s</span><span>"</span> <span>%</span> <span>obj</span><span>.</span><span>beat</span> <span>def</span><span> </span><span>items</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span>return</span> <span>Crime</span><span>.</span><span>objects</span><span>.</span><span>filter</span><span>(</span><span>beat</span><span>=</span><span>obj</span><span>)</span><span>.</span><span>order_by</span><span>(</span><span>"-crime_date"</span><span>)[:</span><span>30</span><span>]</span> </pre></div> </div> <p>为了生成 feed 的 <code><span><title></span></code>、<code><span><link></span></code> 和 <code><span><description></span></code>,Django 使用了 <code><span>title()</span></code>、<code><span>link()</span></code> 和 <code><span>description()</span></code> 方法。在前面的例子中,它们是字符串类属性,但这个例子说明它们可以是字符串 <em>或</em> 方法。对于每一个 <code><span>title</span></code>、<code><span>link</span></code> 和``description``,Django 都遵循这个算法。</p> <ul> <li><p>首先,它试图调用一个方法,传递 <code><span>obj</span></code> 参数,其中 <code><span>obj</span></code> 是 <code><span>get_object()</span></code> 返回的对象。</p></li> <li><p>如果失败了,它就会尝试调用一个没有参数的方法。</p></li> <li><p>如果失败了,它就会使用类属性。</p></li> </ul> <p>还请注意,<code><span>items()</span></code> 也遵循同样的算法——首先,它尝试 <code><span>items(obj)</span></code>,然后是 <code><span>items()</span></code>,最后是 <code><span>items</span></code> 类属性(应该是一个列表)。</p> <p>我们是用一个模板来描述项目。可以是这样的最小化:</p> <div><div><pre><span></span><span>{{</span> <span>obj.description</span> <span>}}</span> </pre></div> </div> <p>但是,你可以根据需要自由添加格式。</p> <p>下面的 <code><span>ExampleFeed</span></code> 类给出了关于 <a><code><span>Feed</span></code></a> 类的方法和属性的完整文档。</p> </section> <section> <span></span><h3>指定 feed 的类型</h3> <p>默认情况下,这个框架中产生的 feed 使用 RSS 2.0。</p> <p>要改变这一点,可以在你的 <a><code><span>Feed</span></code></a> 类中添加一个 <code><span>feed_type</span></code> 属性,像这样:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.utils.feedgenerator</span><span> </span><span>import</span> <span>Atom1Feed</span> <span>class</span><span> </span><span>MyFeed</span><span>(</span><span>Feed</span><span>):</span> <span>feed_type</span> <span>=</span> <span>Atom1Feed</span> </pre></div> </div> <p>请注意,你把 <code><span>feed_type</span></code> 设置为一个类对象,而不是一个实例。</p> <p>目前可用的 feed 类型有:</p> <ul> <li><p><a><code><span>django.utils.feedgenerator.Rss201rev2Feed</span></code></a> (RSS 2.01。默认值。)</p></li> <li><p><a><code><span>django.utils.feedgenerator.RssUserland091Feed</span></code></a> (RSS 0.91。)</p></li> <li><p><a><code><span>django.utils.feedgenerator.Atom1Feed</span></code></a> (Atom 1.0。)</p></li> </ul> </section> <section> <span></span><h3>封面</h3> <p>要指定封面,如创建播客 feed 时使用的封面,使用 <code><span>item_enclosures</span></code> 钩子,或者,如果每个项目只有一个封面,则使用 <code><span>item_enclosure_url</span></code>、<code><span>item_enclosure_length</span></code> 和 <code><span>item_enclosure_mime_type`</span></code> 钩子。请看下面的 <code><span>ExampleFeed</span></code> 类的使用示例。</p> </section> <section> <span></span><h3>语言</h3> <p>Feeds created by the syndication framework automatically include the appropriate <code><span><language></span></code> tag (RSS 2.0) or <code><span>xml:lang</span></code> attribute (Atom). By default, this is <a><code><span>django.utils.translation.get_language()</span></code></a>. You can change it by setting the <code><span>language</span></code> class attribute.</p> </section> <section> <span></span><h3>URL</h3> <p><code><span>link</span></code> 方法/属性可以返回绝对路径(例如 <code><span>"/blog/"</span></code>)或带有完全合格的域和协议的 URL(例如 <code><span>"https://www.example.com/blog/"</span></code>)。如果 <code><span>link</span></code> 不返回域名,那么合成框架将根据你的 <a><code><span>SITE_ID</span> <span>setting</span></code></a> 插入当前站点的域名。</p> <p>Atom feeds 需要一个 <code><span><link</span> <span>rel="self"></span></code>,定义 feed 的当前位置。聚合框架会根据 <a><code><span>SITE_ID</span></code></a> 设置,使用当前网站的域名自动填充。</p> </section> <section> <span></span><h3>同时发布 Atom 和 RSS feed</h3> <p>有些开发者喜欢同时提供 Atom 和 RSS 版本的 feed。要做到这一点,你可以创建一个 <a><code><span>Feed</span></code></a> 类的子类,并将 <code><span>feed_type</span></code> 设置为不同的内容。然后更新你的 URLconf 来添加额外的版本。</p> <p>这有一个完整的例子:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>from</span><span> </span><span>policebeat.models</span><span> </span><span>import</span> <span>NewsItem</span> <span>from</span><span> </span><span>django.utils.feedgenerator</span><span> </span><span>import</span> <span>Atom1Feed</span> <span>class</span><span> </span><span>RssSiteNewsFeed</span><span>(</span><span>Feed</span><span>):</span> <span>title</span> <span>=</span> <span>"Police beat site news"</span> <span>link</span> <span>=</span> <span>"/sitenews/"</span> <span>description</span> <span>=</span> <span>"Updates on changes and additions to police beat central."</span> <span>def</span><span> </span><span>items</span><span>(</span><span>self</span><span>):</span> <span>return</span> <span>NewsItem</span><span>.</span><span>objects</span><span>.</span><span>order_by</span><span>(</span><span>"-pub_date"</span><span>)[:</span><span>5</span><span>]</span> <span>class</span><span> </span><span>AtomSiteNewsFeed</span><span>(</span><span>RssSiteNewsFeed</span><span>):</span> <span>feed_type</span> <span>=</span> <span>Atom1Feed</span> <span>subtitle</span> <span>=</span> <span>RssSiteNewsFeed</span><span>.</span><span>description</span> </pre></div> </div> <div> <p>Note</p> <p>在这个例子中,RSS feed使用 <code><span>description</span></code>,而 Atom feed 使用 <code><span>subtitle</span></code>。这是因为 Atom feed 不提供 feed 级别的“描述”,但它们 <em>提供</em> “副标题”。</p> <p>如果你在你的 <a><code><span>Feed</span></code></a> 类中提供了一个 <code><span>description</span></code>,Django 不会自动将其放入 <code><span>subtitle</span></code> 元素中,因为副标题和描述不一定是一回事。相反,你应该定义一个 <code><span>subtitle</span></code> 属性。</p> <p>在上面的例子中,我们将 Atom feed 的 <code><span>subtitle</span></code> 设置为 RSS feed 的 <code><span>description</span></code>,因为它已经很短了。</p> </div> <p>并附带 URLconf:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.urls</span><span> </span><span>import</span> <span>path</span> <span>from</span><span> </span><span>myproject.feeds</span><span> </span><span>import</span> <span>AtomSiteNewsFeed</span><span>,</span> <span>RssSiteNewsFeed</span> <span>urlpatterns</span> <span>=</span> <span>[</span> <span># ...</span> <span>path</span><span>(</span><span>"sitenews/rss/"</span><span>,</span> <span>RssSiteNewsFeed</span><span>()),</span> <span>path</span><span>(</span><span>"sitenews/atom/"</span><span>,</span> <span>AtomSiteNewsFeed</span><span>()),</span> <span># ...</span> <span>]</span> </pre></div> </div> </section> <section> <span></span><h3><code><span>Feed</span></code> 类参考</h3> <dl> <dt> <em><span>class</span><span> </span></em><span><span>views.</span></span><span><span>Feed</span></span></dt> <dd></dd></dl> <p>这个例子说明了 <a><code><span>Feed</span></code></a> 类的所有可能的属性和方法:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>from</span><span> </span><span>django.utils</span><span> </span><span>import</span> <span>feedgenerator</span> <span>class</span><span> </span><span>ExampleFeed</span><span>(</span><span>Feed</span><span>):</span> <span># FEED TYPE -- Optional. This should be a class that subclasses</span> <span># django.utils.feedgenerator.SyndicationFeed. This designates</span> <span># which type of feed this should be: RSS 2.0, Atom 1.0, etc. If</span> <span># you don't specify feed_type, your feed will be RSS 2.0. This</span> <span># should be a class, not an instance of the class.</span> <span>feed_type</span> <span>=</span> <span>feedgenerator</span><span>.</span><span>Rss201rev2Feed</span> <span># TEMPLATE NAMES -- Optional. These should be strings</span> <span># representing names of Django templates that the system should</span> <span># use in rendering the title and description of your feed items.</span> <span># Both are optional. If a template is not specified, the</span> <span># item_title() or item_description() methods are used instead.</span> <span>title_template</span> <span>=</span> <span>None</span> <span>description_template</span> <span>=</span> <span>None</span> <span># LANGUAGE -- Optional. This should be a string specifying a language</span> <span># code. Defaults to django.utils.translation.get_language().</span> <span>language</span> <span>=</span> <span>"de"</span> <span># TITLE -- One of the following three is required. The framework</span> <span># looks for them in this order.</span> <span>def</span><span> </span><span>title</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the</span> <span> feed's title as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>title</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's title as a normal Python string.</span> <span> """</span> <span>title</span> <span>=</span> <span>"foo"</span> <span># Hard-coded title.</span> <span># LINK -- One of the following three is required. The framework</span> <span># looks for them in this order.</span> <span>def</span><span> </span><span>link</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> # Takes the object returned by get_object() and returns the URL</span> <span> # of the HTML version of the feed as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>link</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the URL of the HTML version of the feed as a normal Python</span> <span> string.</span> <span> """</span> <span>link</span> <span>=</span> <span>"/blog/"</span> <span># Hard-coded URL.</span> <span># FEED_URL -- One of the following three is optional. The framework</span> <span># looks for them in this order.</span> <span>def</span><span> </span><span>feed_url</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> # Takes the object returned by get_object() and returns the feed's</span> <span> # own URL as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>feed_url</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's own URL as a normal Python string.</span> <span> """</span> <span>feed_url</span> <span>=</span> <span>"/blog/rss/"</span> <span># Hard-coded URL.</span> <span># GUID -- One of the following three is optional. The framework looks</span> <span># for them in this order. This property is only used for Atom feeds</span> <span># (where it is the feed-level ID element). If not provided, the feed</span> <span># link is used as the ID.</span> <span>def</span><span> </span><span>feed_guid</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the globally</span> <span> unique ID for the feed as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>feed_guid</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's globally unique ID as a normal Python string.</span> <span> """</span> <span>feed_guid</span> <span>=</span> <span>"/foo/bar/1234"</span> <span># Hard-coded guid.</span> <span># DESCRIPTION -- One of the following three is required. The framework</span> <span># looks for them in this order.</span> <span>def</span><span> </span><span>description</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the feed's</span> <span> description as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>description</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's description as a normal Python string.</span> <span> """</span> <span>description</span> <span>=</span> <span>"Foo bar baz."</span> <span># Hard-coded description.</span> <span># AUTHOR NAME --One of the following three is optional. The framework</span> <span># looks for them in this order.</span> <span>def</span><span> </span><span>author_name</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the feed's</span> <span> author's name as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>author_name</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's author's name as a normal Python string.</span> <span> """</span> <span>author_name</span> <span>=</span> <span>"Sally Smith"</span> <span># Hard-coded author name.</span> <span># AUTHOR EMAIL --One of the following three is optional. The framework</span> <span># looks for them in this order.</span> <span>def</span><span> </span><span>author_email</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the feed's</span> <span> author's email as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>author_email</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's author's email as a normal Python string.</span> <span> """</span> <span>author_email</span> <span>=</span> <span>"test@example.com"</span> <span># Hard-coded author email.</span> <span># AUTHOR LINK --One of the following three is optional. The framework</span> <span># looks for them in this order. In each case, the URL should include</span> <span># the scheme (such as "https://") and domain name.</span> <span>def</span><span> </span><span>author_link</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the feed's</span> <span> author's URL as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>author_link</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's author's URL as a normal Python string.</span> <span> """</span> <span>author_link</span> <span>=</span> <span>"https://www.example.com/"</span> <span># Hard-coded author URL.</span> <span># CATEGORIES -- One of the following three is optional. The framework</span> <span># looks for them in this order. In each case, the method/attribute</span> <span># should return an iterable object that returns strings.</span> <span>def</span><span> </span><span>categories</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the feed's</span> <span> categories as iterable over strings.</span> <span> """</span> <span>def</span><span> </span><span>categories</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's categories as iterable over strings.</span> <span> """</span> <span>categories</span> <span>=</span> <span>[</span><span>"python"</span><span>,</span> <span>"django"</span><span>]</span> <span># Hard-coded list of categories.</span> <span># COPYRIGHT NOTICE -- One of the following three is optional. The</span> <span># framework looks for them in this order.</span> <span>def</span><span> </span><span>feed_copyright</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the feed's</span> <span> copyright notice as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>feed_copyright</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's copyright notice as a normal Python string.</span> <span> """</span> <span>feed_copyright</span> <span>=</span> <span>"Copyright (c) 2007, Sally Smith"</span> <span># Hard-coded copyright notice.</span> <span># TTL -- One of the following three is optional. The framework looks</span> <span># for them in this order. Ignored for Atom feeds.</span> <span>def</span><span> </span><span>ttl</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the feed's</span> <span> TTL (Time To Live) as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>ttl</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's TTL as a normal Python string.</span> <span> """</span> <span>ttl</span> <span>=</span> <span>600</span> <span># Hard-coded Time To Live.</span> <span># STYLESHEETS -- Optional. To set, provide one of the following three.</span> <span># The framework looks for them in this order.</span> <span>def</span><span> </span><span>stylesheets</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns the feed's</span> <span> stylesheets (as URL strings or as Stylesheet instances).</span> <span> """</span> <span>def</span><span> </span><span>stylesheets</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the feed's stylesheets (as URL strings or Stylesheet</span> <span> instances).</span> <span> """</span> <span># Hardcoded stylesheets.</span> <span>stylesheets</span> <span>=</span> <span>[</span><span>"/stylesheet1.xsl"</span><span>,</span> <span>"stylesheet2.xsl"</span><span>]</span> <span># ITEMS -- One of the following three is required. The framework looks</span> <span># for them in this order.</span> <span>def</span><span> </span><span>items</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes the object returned by get_object() and returns a list of</span> <span> items to publish in this feed.</span> <span> """</span> <span>def</span><span> </span><span>items</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns a list of items to publish in this feed.</span> <span> """</span> <span>items</span> <span>=</span> <span>[</span><span>"Item 1"</span><span>,</span> <span>"Item 2"</span><span>]</span> <span># Hard-coded items.</span> <span># GET_OBJECT -- This is required for feeds that publish different data</span> <span># for different URL parameters. (See "A complex example" above.)</span> <span>def</span><span> </span><span>get_object</span><span>(</span><span>self</span><span>,</span> <span>request</span><span>,</span> <span>*</span><span>args</span><span>,</span> <span>**</span><span>kwargs</span><span>):</span> <span> </span><span>"""</span> <span> Takes the current request and the arguments from the URL, and</span> <span> returns an object represented by this feed. Raises</span> <span> django.core.exceptions.ObjectDoesNotExist on error.</span> <span> """</span> <span># ITEM TITLE AND DESCRIPTION -- If title_template or</span> <span># description_template are not defined, these are used instead. Both are</span> <span># optional, by default they will use the string representation of the</span> <span># item.</span> <span>def</span><span> </span><span>item_title</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> title as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>item_title</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the title for every item in the feed.</span> <span> """</span> <span>item_title</span> <span>=</span> <span>"Breaking News: Nothing Happening"</span> <span># Hard-coded title.</span> <span>def</span><span> </span><span>item_description</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> description as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>item_description</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the description for every item in the feed.</span> <span> """</span> <span>item_description</span> <span>=</span> <span>"A description of the item."</span> <span># Hard-coded description.</span> <span>def</span><span> </span><span>get_context_data</span><span>(</span><span>self</span><span>,</span> <span>**</span><span>kwargs</span><span>):</span> <span> </span><span>"""</span> <span> Returns a dictionary to use as extra context if either</span> <span> description_template or item_template are used.</span> <span> Default implementation preserves the old behavior</span> <span> of using {'obj': item, 'site': current_site} as the context.</span> <span> """</span> <span># ITEM LINK -- One of these three is required. The framework looks for</span> <span># them in this order.</span> <span># First, the framework tries the two methods below, in</span> <span># order. Failing that, it falls back to the get_absolute_url()</span> <span># method on each item returned by items().</span> <span>def</span><span> </span><span>item_link</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's URL.</span> <span> """</span> <span>def</span><span> </span><span>item_link</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the URL for every item in the feed.</span> <span> """</span> <span># ITEM_GUID -- The following method is optional. If not provided, the</span> <span># item's link is used by default.</span> <span>def</span><span> </span><span>item_guid</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as return by items(), and returns the item's ID.</span> <span> """</span> <span># ITEM_GUID_IS_PERMALINK -- The following method is optional. If</span> <span># provided, it sets the 'isPermaLink' attribute of an item's</span> <span># GUID element. This method is used only when 'item_guid' is</span> <span># specified.</span> <span>def</span><span> </span><span>item_guid_is_permalink</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns a boolean.</span> <span> """</span> <span>item_guid_is_permalink</span> <span>=</span> <span>False</span> <span># Hardcoded value</span> <span># ITEM AUTHOR NAME -- One of the following three is optional. The</span> <span># framework looks for them in this order.</span> <span>def</span><span> </span><span>item_author_name</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> author's name as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>item_author_name</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the author name for every item in the feed.</span> <span> """</span> <span>item_author_name</span> <span>=</span> <span>"Sally Smith"</span> <span># Hard-coded author name.</span> <span># ITEM AUTHOR EMAIL --One of the following three is optional. The</span> <span># framework looks for them in this order.</span> <span>#</span> <span># If you specify this, you must specify item_author_name.</span> <span>def</span><span> </span><span>item_author_email</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> author's email as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>item_author_email</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the author email for every item in the feed.</span> <span> """</span> <span>item_author_email</span> <span>=</span> <span>"test@example.com"</span> <span># Hard-coded author email.</span> <span># ITEM AUTHOR LINK -- One of the following three is optional. The</span> <span># framework looks for them in this order. In each case, the URL should</span> <span># include the scheme (such as "https://") and domain name.</span> <span>#</span> <span># If you specify this, you must specify item_author_name.</span> <span>def</span><span> </span><span>item_author_link</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> author's URL as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>item_author_link</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the author URL for every item in the feed.</span> <span> """</span> <span>item_author_link</span> <span>=</span> <span>"https://www.example.com/"</span> <span># Hard-coded author URL.</span> <span># ITEM ENCLOSURES -- One of the following three is optional. The</span> <span># framework looks for them in this order. If one of them is defined,</span> <span># ``item_enclosure_url``, ``item_enclosure_length``, and</span> <span># ``item_enclosure_mime_type`` will have no effect.</span> <span>def</span><span> </span><span>item_enclosures</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns a list of</span> <span> ``django.utils.feedgenerator.Enclosure`` objects.</span> <span> """</span> <span>def</span><span> </span><span>item_enclosures</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the ``django.utils.feedgenerator.Enclosure`` list for every</span> <span> item in the feed.</span> <span> """</span> <span>item_enclosures</span> <span>=</span> <span>[]</span> <span># Hard-coded enclosure list</span> <span># ITEM ENCLOSURE URL -- One of these three is required if you're</span> <span># publishing enclosures and you're not using ``item_enclosures``. The</span> <span># framework looks for them in this order.</span> <span>def</span><span> </span><span>item_enclosure_url</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> enclosure URL.</span> <span> """</span> <span>def</span><span> </span><span>item_enclosure_url</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the enclosure URL for every item in the feed.</span> <span> """</span> <span>item_enclosure_url</span> <span>=</span> <span>"/foo/bar.mp3"</span> <span># Hard-coded enclosure link.</span> <span># ITEM ENCLOSURE LENGTH -- One of these three is required if you're</span> <span># publishing enclosures and you're not using ``item_enclosures``. The</span> <span># framework looks for them in this order. In each case, the returned</span> <span># value should be either an integer, or a string representation of the</span> <span># integer, in bytes.</span> <span>def</span><span> </span><span>item_enclosure_length</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> enclosure length.</span> <span> """</span> <span>def</span><span> </span><span>item_enclosure_length</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the enclosure length for every item in the feed.</span> <span> """</span> <span>item_enclosure_length</span> <span>=</span> <span>32000</span> <span># Hard-coded enclosure length.</span> <span># ITEM ENCLOSURE MIME TYPE -- One of these three is required if you're</span> <span># publishing enclosures and you're not using ``item_enclosures``. The</span> <span># framework looks for them in this order.</span> <span>def</span><span> </span><span>item_enclosure_mime_type</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> enclosure MIME type.</span> <span> """</span> <span>def</span><span> </span><span>item_enclosure_mime_type</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the enclosure MIME type for every item in the feed.</span> <span> """</span> <span>item_enclosure_mime_type</span> <span>=</span> <span>"audio/mpeg"</span> <span># Hard-coded enclosure MIME type.</span> <span># ITEM PUBDATE -- It's optional to use one of these three. This is a</span> <span># hook that specifies how to get the pubdate for a given item.</span> <span># In each case, the method/attribute should return a Python</span> <span># datetime.datetime object.</span> <span>def</span><span> </span><span>item_pubdate</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> pubdate.</span> <span> """</span> <span>def</span><span> </span><span>item_pubdate</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the pubdate for every item in the feed.</span> <span> """</span> <span>item_pubdate</span> <span>=</span> <span>datetime</span><span>.</span><span>datetime</span><span>(</span><span>2005</span><span>,</span> <span>5</span><span>,</span> <span>3</span><span>)</span> <span># Hard-coded pubdate.</span> <span># ITEM UPDATED -- It's optional to use one of these three. This is a</span> <span># hook that specifies how to get the updateddate for a given item.</span> <span># In each case, the method/attribute should return a Python</span> <span># datetime.datetime object.</span> <span>def</span><span> </span><span>item_updateddate</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> updateddate.</span> <span> """</span> <span>def</span><span> </span><span>item_updateddate</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the updateddate for every item in the feed.</span> <span> """</span> <span>item_updateddate</span> <span>=</span> <span>datetime</span><span>.</span><span>datetime</span><span>(</span><span>2005</span><span>,</span> <span>5</span><span>,</span> <span>3</span><span>)</span> <span># Hard-coded updateddate.</span> <span># ITEM CATEGORIES -- It's optional to use one of these three. This is</span> <span># a hook that specifies how to get the list of categories for a given</span> <span># item. In each case, the method/attribute should return an iterable</span> <span># object that returns strings.</span> <span>def</span><span> </span><span>item_categories</span><span>(</span><span>self</span><span>,</span> <span>item</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> categories.</span> <span> """</span> <span>def</span><span> </span><span>item_categories</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the categories for every item in the feed.</span> <span> """</span> <span>item_categories</span> <span>=</span> <span>[</span><span>"python"</span><span>,</span> <span>"django"</span><span>]</span> <span># Hard-coded categories.</span> <span># ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the</span> <span># following three is optional. The framework looks for them in this</span> <span># order.</span> <span>def</span><span> </span><span>item_copyright</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> copyright notice as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>item_copyright</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the copyright notice for every item in the feed.</span> <span> """</span> <span>item_copyright</span> <span>=</span> <span>"Copyright (c) 2007, Sally Smith"</span> <span># Hard-coded copyright notice.</span> <span># ITEM COMMENTS URL -- It's optional to use one of these three. This is</span> <span># a hook that specifies how to get the URL of a page for comments for a</span> <span># given item.</span> <span>def</span><span> </span><span>item_comments</span><span>(</span><span>self</span><span>,</span> <span>obj</span><span>):</span> <span> </span><span>"""</span> <span> Takes an item, as returned by items(), and returns the item's</span> <span> comments URL as a normal Python string.</span> <span> """</span> <span>def</span><span> </span><span>item_comments</span><span>(</span><span>self</span><span>):</span> <span> </span><span>"""</span> <span> Returns the comments URL for every item in the feed.</span> <span> """</span> <span>item_comments</span> <span>=</span> <span>"https://www.example.com/comments"</span> <span># Hard-coded comments URL</span> </pre></div> </div> </section> </section> <section> <span></span><h2>低级框架</h2> <p>在幕后,高级 RSS 框架使用一个低级框架来生成 feed 的 XML。这个框架存在于一个模块中:<a href="https://github.com/django/django/blob/main/django/utils/feedgenerator.py">django/utils/feedgenerator.py</a>。</p> <p>你可以自己使用这个框架,进行低级的 feed 生成。你也可以创建自定义的 feed 生成器子类,用于 <code><span>feed_type</span></code> <code><span>Feed</span></code> 选项。</p> <section> <span></span><h3><code><span>SyndicationFeed</span></code> 类</h3> <p><a><code><span>feedgenerator</span></code></a> 模块包含一个基类:</p> <ul> <li><p><a><code><span>django.utils.feedgenerator.SyndicationFeed</span></code></a></p></li> </ul> <p>和几个子类:</p> <ul> <li><p><a><code><span>django.utils.feedgenerator.RssUserland091Feed</span></code></a></p></li> <li><p><a><code><span>django.utils.feedgenerator.Rss201rev2Feed</span></code></a></p></li> <li><p><a><code><span>django.utils.feedgenerator.Atom1Feed</span></code></a></p></li> </ul> <p>这三个类中的每一个都知道如何将某种类型的 feed 渲染成 XML。它们共享这个接口:</p> <dl> <dt><a><code><span>SyndicationFeed.__init__()</span></code></a></dt><dd><p>用给定的元数据字典初始化 feed,该字典适用于整个 feed。所需的关键字参数有:</p> <ul> <li><p><code><span>title</span></code></p></li> <li><p><code><span>link</span></code></p></li> <li><p><code><span>description</span></code></p></li> </ul> <p>还有一堆其他可选的关键词:</p> <ul> <li><p><code><span>language</span></code></p></li> <li><p><code><span>author_email</span></code></p></li> <li><p><code><span>author_name</span></code></p></li> <li><p><code><span>author_link</span></code></p></li> <li><p><code><span>subtitle</span></code></p></li> <li><p><code><span>categories</span></code></p></li> <li><p><code><span>feed_url</span></code></p></li> <li><p><code><span>feed_copyright</span></code></p></li> <li><p><code><span>feed_guid</span></code></p></li> <li><p><code><span>ttl</span></code></p></li> <li><p><code><span>stylesheets</span></code></p></li> </ul> <p>你传递给 <code><span>__init__</span></code> 的任何额外的关键字参数将被存储在 <code><span>self.feed</span></code> 中,供 <a>自定义 feed 生成器</a> 使用。</p> <p>All parameters should be strings, except for two:</p> <ul> <li><p><code><span>categories</span></code> 应是一个字符串序列。</p></li> <li><p><code><span>stylesheets</span></code> should be a sequence of either strings or <a><code><span>Stylesheet</span></code></a> instances.</p></li> </ul> <p>Beware that some control characters are <a href="https://www.w3.org/International/questions/qa-controls">not allowed</a> in XML documents. If your content has some of them, you might encounter a <a href="https://docs.python.org/3/library/exceptions.html#ValueError"><code><span>ValueError</span></code></a> when producing the feed.</p> <div> <span>Changed in Django 5.2:</span> <p>The <code><span>stylesheets</span></code> argument was added.</p> </div> </dd> <dt><a><code><span>SyndicationFeed.add_item()</span></code></a></dt><dd><p>用给定的参数将一个项目添加到 feed 中。</p> <p>必须的关键字参数是:</p> <ul> <li><p><code><span>title</span></code></p></li> <li><p><code><span>link</span></code></p></li> <li><p><code><span>description</span></code></p></li> </ul> <p>可选的关键字参数是:</p> <ul> <li><p><code><span>author_email</span></code></p></li> <li><p><code><span>author_name</span></code></p></li> <li><p><code><span>author_link</span></code></p></li> <li><p><code><span>pubdate</span></code></p></li> <li><p><code><span>comments</span></code></p></li> <li><p><code><span>unique_id</span></code></p></li> <li><p><code><span>enclosures</span></code></p></li> <li><p><code><span>categories</span></code></p></li> <li><p><code><span>item_copyright</span></code></p></li> <li><p><code><span>ttl</span></code></p></li> <li><p><code><span>updateddate</span></code></p></li> </ul> <p>额外的关键字参数将被存储在 <a>自定义 feed 生成器</a> 。</p> <p>所有参数,如果给定,都应该是字符串,除了:</p> <ul> <li><p><code><span>pubdate</span></code> 应该是一个 Python <a href="https://docs.python.org/3/library/datetime.html#datetime.datetime"><code><span>datetime</span></code></a> 对象。</p></li> <li><p><code><span>updateddate</span></code> 应该是一个 Python <a href="https://docs.python.org/3/library/datetime.html#datetime.datetime"><code><span>datetime</span></code></a> 对象。</p></li> <li><p><code><span>enclosures</span></code> 应该是一个 <code><span>django.utils.feedgenerator.Eclosure</span></code> 实例的列表。</p></li> <li><p><code><span>categories</span></code> 应是一个字符串序列。</p></li> </ul> </dd> <dt><a><code><span>SyndicationFeed.write()</span></code></a></dt><dd><p>将给定编码的 feed 输出到 outfile,一个类似文件的对象。</p> </dd> <dt><a><code><span>SyndicationFeed.writeString()</span></code></a></dt><dd><p>以给定编码的字符串形式返回 feed。</p> </dd> </dl> <p>例如,要创建一个 Atom 1.0 订阅源并将其打印到标准输出:</p> <div><div><pre><span></span><span>>>> </span><span>from</span><span> </span><span>django.utils</span><span> </span><span>import</span> <span>feedgenerator</span> <span>>>> </span><span>from</span><span> </span><span>datetime</span><span> </span><span>import</span> <span>datetime</span> <span>>>> </span><span>f</span> <span>=</span> <span>feedgenerator</span><span>.</span><span>Atom1Feed</span><span>(</span> <span>... </span> <span>title</span><span>=</span><span>"My Blog"</span><span>,</span> <span>... </span> <span>link</span><span>=</span><span>"https://www.example.com/"</span><span>,</span> <span>... </span> <span>description</span><span>=</span><span>"In which I write about what I ate today."</span><span>,</span> <span>... </span> <span>language</span><span>=</span><span>"en"</span><span>,</span> <span>... </span> <span>author_name</span><span>=</span><span>"Myself"</span><span>,</span> <span>... </span> <span>feed_url</span><span>=</span><span>"https://example.com/atom.xml"</span><span>,</span> <span>... </span><span>)</span> <span>>>> </span><span>f</span><span>.</span><span>add_item</span><span>(</span> <span>... </span> <span>title</span><span>=</span><span>"Hot dog today"</span><span>,</span> <span>... </span> <span>link</span><span>=</span><span>"https://www.example.com/entries/1/"</span><span>,</span> <span>... </span> <span>pubdate</span><span>=</span><span>datetime</span><span>.</span><span>now</span><span>(),</span> <span>... </span> <span>description</span><span>=</span><span>"<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>"</span><span>,</span> <span>... </span><span>)</span> <span>>>> </span><span>print</span><span>(</span><span>f</span><span>.</span><span>writeString</span><span>(</span><span>"UTF-8"</span><span>))</span> <span><?xml version="1.0" encoding="UTF-8"?></span> <span><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"></span> <span>...</span> <span></feed></span> </pre></div> </div> </section> <section> <span></span><h3>自定义 feed 生成器</h3> <p>如果你需要制作一个自定义的 feed 格式,你有几个选择。</p> <p>如果 feed 格式是完全自定义的,你会想要子类化 <code><span>SyndicationFeed</span></code> 并完全替换 <code><span>write()</span></code> 和 <code><span>writeString()</span></code> 方法。</p> <p>然而,如果 feed 格式是 RSS 或 Atom 的衍生产品(即 <a href="https://georss.org">GeoRSS</a> ,苹果的 <a href="https://help.apple.com/itc/podcasts_connect/#/itcb54353390">iTunes podcast format</a> 等),你就有了更好的选择。这些类型的 feeds 通常会向底层格式添加额外的元素和/或属性,而且 <code><span>SyndicationFeed</span></code> 调用一组方法来获取这些额外的属性。因此,你可以子类化适当的 feed 生成器类(<code><span>Atom1Feed</span></code> 或 <code><span>Rss201rev2Feed</span></code>)并扩展这些回调。它们是:</p> <dl> <dt><code><span>SyndicationFeed.root_attributes(self)</span></code></dt><dd><p>返回一个属性的 <code><span>dict</span></code> 以添加到根 feed 元素(<code><span>feed</span></code>/<code><span>channel</span></code>)。</p> </dd> <dt><code><span>SyndicationFeed.add_root_elements(self,</span> <span>handler)</span></code></dt><dd><p>回调以在根 feed 元素(<code><span>feed</span></code>/<code><span>channel</span></code>)中添加元素。<code><span>handler</span></code> 是一个 <a href="https://docs.python.org/3/library/xml.sax.utils.html#xml.sax.saxutils.XMLGenerator"><code><span>XMLGenerator</span></code></a>,来自 Python 内置的 SAX 库;你将调用它上的方法来添加到正在处理的 XML 文档中。</p> </dd> <dt><code><span>SyndicationFeed.item_attributes(self,</span> <span>item)</span></code></dt><dd><p>返回要添加到每个项目(<code><span>item</span></code>/<code><span>entry</span></code>)元素的 <code><span>dict</span></code> 属性。参数 <code><span>item</span></code> 是传递给 <code><span>SyndicationFeed.add_item()</span></code> 的所有数据的字典。</p> </dd> <dt><code><span>SyndicationFeed.add_item_elements(self,</span> <span>handler,</span> <span>item)</span></code></dt><dd><p>回调为每个项目(<code><span>item</span></code>/<code><span>entry</span></code>)元素添加元素。<code><span>handler</span></code> 和 <code><span>item</span></code> 同上。</p> </dd> </dl> <div> <p>Warning</p> <p>如果你覆盖了这些方法中的任何一个,一定要调用超级类方法,因为它们为每种 feed 格式添加了所需的元素。</p> </div> <p>例如,你可以这样开始实现一个 iTunes RSS feed 生成器:</p> <div><div><pre><span></span><span>class</span><span> </span><span>iTunesFeed</span><span>(</span><span>Rss201rev2Feed</span><span>):</span> <span>def</span><span> </span><span>root_attributes</span><span>(</span><span>self</span><span>):</span> <span>attrs</span> <span>=</span> <span>super</span><span>()</span><span>.</span><span>root_attributes</span><span>()</span> <span>attrs</span><span>[</span><span>"xmlns:itunes"</span><span>]</span> <span>=</span> <span>"http://www.itunes.com/dtds/podcast-1.0.dtd"</span> <span>return</span> <span>attrs</span> <span>def</span><span> </span><span>add_root_elements</span><span>(</span><span>self</span><span>,</span> <span>handler</span><span>):</span> <span>super</span><span>()</span><span>.</span><span>add_root_elements</span><span>(</span><span>handler</span><span>)</span> <span>handler</span><span>.</span><span>addQuickElement</span><span>(</span><span>"itunes:explicit"</span><span>,</span> <span>"clean"</span><span>)</span> </pre></div> </div> <p>对于一个完整的自定义 feed 类来说,还有很多工作要做,但上面的例子应该展示了基本的想法。</p> </section> <section> <span></span><span></span><span></span><h3>Feed stylesheets</h3> <div> <span>New in Django 5.2.</span> </div> <p>If you wish to have your RSS feed render nicely in a browser, you will need to provide styling information for the XML file, typically in <a href="https://developer.mozilla.org/en-US/docs/Web/XSLT/Transforming_XML_with_XSLT">XSLT</a> or CSS formats.</p> <p>You can add this to your RSS feed by setting the <code><span>stylesheets</span></code> attribute on the feed class.</p> <p>This can be a hardcoded URL:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>class</span><span> </span><span>FeedWithHardcodedStylesheet</span><span>(</span><span>Feed</span><span>):</span> <span>stylesheets</span> <span>=</span> <span>[</span> <span>"https://example.com/rss_stylesheet.xslt"</span><span>,</span> <span>]</span> </pre></div> </div> <p>You can also use Django's static files system:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>from</span><span> </span><span>django.templatetags.static</span><span> </span><span>import</span> <span>static</span> <span>class</span><span> </span><span>FeedWithStaticFileStylesheet</span><span>(</span><span>Feed</span><span>):</span> <span>stylesheets</span> <span>=</span> <span>[</span> <span>static</span><span>(</span><span>"rss_styles.xslt"</span><span>),</span> <span>]</span> </pre></div> </div> <p>Another option is to have a view in your project that renders the XSLT document. You can then link it like so:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>from</span><span> </span><span>django.urls</span><span> </span><span>import</span> <span>reverse_lazy</span> <span>class</span><span> </span><span>FeedWithStylesheetView</span><span>(</span><span>Feed</span><span>):</span> <span>stylesheets</span> <span>=</span> <span>[</span> <span>reverse_lazy</span><span>(</span><span>"your-custom-view-name"</span><span>),</span> <span>]</span> </pre></div> </div> <p>Django will normally try to guess the MIME type of the given URL based on its extension, but if that fails you can specify it using the <a><code><span>Stylesheet</span></code></a> class:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>from</span><span> </span><span>django.utils.feedgenerator</span><span> </span><span>import</span> <span>Stylesheet</span> <span>class</span><span> </span><span>FeedWithHardcodedStylesheet</span><span>(</span><span>Feed</span><span>):</span> <span>stylesheets</span> <span>=</span> <span>[</span> <span>Stylesheet</span><span>(</span><span>"https://example.com/rss_stylesheet"</span><span>,</span> <span>mimetype</span><span>=</span><span>"text/xsl"</span><span>),</span> <span>]</span> </pre></div> </div> <p>Similarly, if you'd like to use a different <code><span>media</span></code> attribute than <code><span>screen</span></code> (Django's default), you can use the <a><code><span>Stylesheet</span></code></a> class again:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>from</span><span> </span><span>django.utils.feedgenerator</span><span> </span><span>import</span> <span>Stylesheet</span> <span>class</span><span> </span><span>FeedWithHardcodedStylesheet</span><span>(</span><span>Feed</span><span>):</span> <span>stylesheets</span> <span>=</span> <span>[</span> <span>Stylesheet</span><span>(</span><span>"https://example.com/rss_stylesheet.xslt"</span><span>,</span> <span>media</span><span>=</span><span>"print"</span><span>),</span> <span>]</span> </pre></div> </div> <p>Any of these options can be combined when using multiple stylesheets:</p> <div><div><pre><span></span><span>from</span><span> </span><span>django.contrib.syndication.views</span><span> </span><span>import</span> <span>Feed</span> <span>from</span><span> </span><span>django.utils.feedgenerator</span><span> </span><span>import</span> <span>Stylesheet</span> <span>class</span><span> </span><span>MultiStylesheetFeed</span><span>(</span><span>Feed</span><span>):</span> <span>stylesheets</span> <span>=</span> <span>[</span> <span>"/stylesheet1.xsl"</span><span>,</span> <span>Stylesheet</span><span>(</span><span>"/stylesheet2.xsl"</span><span>),</span> <span>]</span> </pre></div> </div> </section> </section> </section> </div> <!--end::Text--> </div> <!--end::Description--> <div class="mt-5"> <!--关键词搜索--> <a href="/index.php?s=article&c=search&keyword=Django" class="badge badge-light-primary fw-bold my-2" target="_blank">Django</a> <a href="/index.php?s=article&c=search&keyword=Python" class="badge badge-light-primary fw-bold my-2" target="_blank">Python</a> <a href="/index.php?s=article&c=search&keyword=API%E5%8F%82%E8%80%83" class="badge badge-light-primary fw-bold my-2" target="_blank">API参考</a> <a href="/index.php?s=article&c=search&keyword=Web%E5%BC%80%E5%8F%91" class="badge badge-light-primary fw-bold my-2" target="_blank">Web开发</a> </div> <div class="mt-5"> <p class="fc-show-prev-next"> <strong>上一篇:</strong><a href="/web/840144.html">Django参考文档:staticfiles 应用</a><br> </p> <p class="fc-show-prev-next"> <strong>下一篇:</strong><a href="/web/840146.html">Django参考文档:Content Security Policy</a> </p> </div> <!--begin::Block--> <div class="d-flex flex-stack mb-2 mt-10"> <!--begin::Title--> <h3 class="text-dark fs-5 fw-bold text-gray-800">相关内容</h3> <!--end::Title--> </div> <div class="separator separator-dashed mb-9"></div> <!--end::Block--> <div class="row g-10"> </div> </div> <!--end::Table widget 14--> </div> <!--end::Col--> <!--begin::Col--> <div class="col-xl-4 mt-0"> <!--begin::Chart Widget 35--> <div class="card card-flush h-md-100"> <!--begin::Header--> <div class="card-header pt-5 "> <!--begin::Title--> <h3 class="card-title align-items-start flex-column"> <!--begin::Statistics--> <div class="d-flex align-items-center mb-2"> <!--begin::Currency--> <span class="fs-5 fw-bold text-gray-800 ">热门资讯</span> <!--end::Currency--> </div> <!--end::Statistics--> </h3> <!--end::Title--> </div> <!--end::Header--> <!--begin::Body--> <div class="card-body pt-3"> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('https://wp-com.uploads.cn/wp-content/uploads/2023/11/20231120045450170042729048128.jpg#系统开启了相对路径模式,本地址是站外域名,不能转为相对路径(在关闭开发者模式后不显示这句话)#没有设置高宽参数,将以原图输出')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/839945.html" class="text-dark fw-bold text-hover-primary fs-6">玻璃硬盘原理图 玻璃硬盘原理</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">玻璃硬盘,又称为磁头悬浮硬盘(Magnetic Head Flying Disk,MHFD),是一种...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('https://wp-com.uploads.cn/wp-content/uploads/2023/11/0f6c4ed6839b19be-c5dca4fa7ea3e591-bc0f8057e935984a423b128cd7b63f68-36.jpg#系统开启了相对路径模式,本地址是站外域名,不能转为相对路径(在关闭开发者模式后不显示这句话)#没有设置高宽参数,将以原图输出')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/839930.html" class="text-dark fw-bold text-hover-primary fs-6">闲鱼搜索规则与技巧 闲鱼最新特...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">在闲鱼这个二手交易平台上,有很多用户都希望能够找到一些特殊的东西,比如一些罕见的收藏品、独特的手工艺...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('https://wp-com.uploads.cn/wp-content/uploads/2023/11/20231115031556169998935641809.jpg#系统开启了相对路径模式,本地址是站外域名,不能转为相对路径(在关闭开发者模式后不显示这句话)#没有设置高宽参数,将以原图输出')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/838629.html" class="text-dark fw-bold text-hover-primary fs-6">家里监控最长能保存多少天的记录...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">家里监控一般保存多久 随着科技的发展,家庭监控系统已经成为了许多家庭的必备设备,它不仅可以帮助我们...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/uploadfile/202411/f764957d34417a8.jpg#没有设置高宽参数,将以原图输出')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/839896.html" class="text-dark fw-bold text-hover-primary fs-6">华为tag有用吗 华为tag-...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">华为Tag是华为手机中的一种功能,它可以帮助用户更好地管理自己的手机数据和应用,通过使用华为Tag,...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('https://wp-com.uploads.cn/wp-content/uploads/2023/11/20231114051725169991024597032.jpg#系统开启了相对路径模式,本地址是站外域名,不能转为相对路径(在关闭开发者模式后不显示这句话)#没有设置高宽参数,将以原图输出')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/838256.html" class="text-dark fw-bold text-hover-primary fs-6">ps5手柄可用手机快充充电吗 ...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">PS5手柄,即PlayStation 5的DualSense手柄,是索尼公司为PlayStation...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/212.html" class="text-dark fw-bold text-hover-primary fs-6">QQ音乐提示代理模式可能无法正...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">QQ音乐提示代理模式可能无法正常访问,如上图所示,是怎么回事呢? 这个可能和你的网络设置有关系,首先...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('https://wp-com.uploads.cn/wp-content/uploads/2023/11/20231115042338169999341869227.jpg#系统开启了相对路径模式,本地址是站外域名,不能转为相对路径(在关闭开发者模式后不显示这句话)#没有设置高宽参数,将以原图输出')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/838648.html" class="text-dark fw-bold text-hover-primary fs-6">收到微信有提示音怎么去掉 微信...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">微信收到信息没有提示音,可能是由多种原因导致的,以下是一些可能的原因及解决方法: 1. 手机静音或...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('/static/assets/images/nopic.gif')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/831913.html" class="text-dark fw-bold text-hover-primary fs-6">a100显卡对应的cuda版本</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">在进行GPU加速的编程中,CUDA是常用的架构和平台,其版本和显卡型号之间存在着一定的对应关系。本篇...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('https://wp-com.uploads.cn/wp-content/uploads/2023/11/20231114094424169992626476822.jpg#系统开启了相对路径模式,本地址是站外域名,不能转为相对路径(在关闭开发者模式后不显示这句话)#没有设置高宽参数,将以原图输出')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/838337.html" class="text-dark fw-bold text-hover-primary fs-6">别人打电话听不见我说话怎么回事...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">当我们在使用手机时,可能会遇到别人打电话过来听不见声音的情况,这种情况可能是由多种原因导致的,下面我...</span> </div> <!--end::Title--> </div> <!--begin::Item--> <div class="d-flex flex-stack mb-7"> <!--begin::Symbol--> <div class="symbol symbol-60px symbol-2by3 me-4"> <div class="symbol-label" style="background-image: url('https://wp-com.uploads.cn/wp-content/uploads/2023/11/20231115082135170000769520125.jpg#系统开启了相对路径模式,本地址是站外域名,不能转为相对路径(在关闭开发者模式后不显示这句话)#没有设置高宽参数,将以原图输出')"></div> </div> <!--end::Symbol--> <!--begin::Title--> <div class="m-0"> <a href="/web/838710.html" class="text-dark fw-bold text-hover-primary fs-6">苹果手机非通讯录电话打不进来 ...</a> <span class="text-gray-600 fw-semibold d-block pt-1 fs-7">手机电话打不进来可能有多种原因,以下是一些常见的问题及解决方法: 1. **信号问题**: ...</span> </div> <!--end::Title--> </div> </div> <!--end::Body--> </div> <!--end::Chart Widget 35--> </div> <!--end::Col--> </div> </div> <!--end::Content container--> </div> <!--end::Content--> </div> <!--end::Content wrapper--> <!--begin::Footer--> <div id="kt_app_footer" class="app-footer"> <!--begin::Footer container--> <div class="app-container container-xxl d-flex flex-column flex-md-row flex-center flex-md-stack py-3"> <!--begin::Copyright--> <div class="text-dark order-2 order-md-1"> <span class="text-muted fw-semibold me-1">2026 ©</span> 晓说杂谈<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?f7b4581e1f9f88ac28d46df58a8d3ff5"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <a target="_blank" href="https://beian.miit.gov.cn/">豫ICP备13019747号-13</a> </div> <!--end::Copyright--> <!--begin::Menu--> <ul class="menu menu-gray-600 menu-hover-primary fw-semibold order-1"> <li class="menu-item"> <a href="/tech" target="_blank" class="menu-link px-2">科技分享</a> </li> <li class="menu-item"> <a href="/web" target="_blank" class="menu-link px-2">网络技术</a> </li> <li class="menu-item"> <a href="/hardware" target="_blank" class="menu-link px-2">硬件设备</a> </li> <li class="menu-item"> <a href="/program" target="_blank" class="menu-link px-2">程序人生</a> </li> <li class="menu-item"> <a href="/jinrong" target="_blank" class="menu-link px-2">探索发现</a> </li> <li class="menu-item"> <a href="/jixie" target="_blank" class="menu-link px-2">机械加工</a> </li> <li class="menu-item"> <a href="/dianshang" target="_blank" class="menu-link px-2">电商</a> </li> <li class="menu-item"> <a href="/other" target="_blank" class="menu-link px-2">其他</a> </li> <li class="menu-item"> <a href="/zhishi" target="_blank" class="menu-link px-2">日常知识</a> </li> <li class="menu-item"> <a href="/yulu" target="_blank" class="menu-link px-2">每日语录</a> </li> </ul> <!--end::Menu--> </div> <!--end::Footer container--> </div> <!--end::Footer--> </div> <!--end:::Main--> </div> <!--end::Wrapper--> </div> <!--end::Page--> </div> <!--end::App--> <div id="kt_scrolltop" class="scrolltop" data-kt-scrolltop="true"> <!--begin::Svg Icon | path: icons/duotune/arrows/arr066.svg--> <span class="svg-icon"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect opacity="0.5" x="13" y="6" width="13" height="2" rx="1" transform="rotate(90 13 6)" fill="currentColor"></rect> <path d="M12.5657 8.56569L16.75 12.75C17.1642 13.1642 17.8358 13.1642 18.25 12.75C18.6642 12.3358 18.6642 11.6642 18.25 11.25L12.7071 5.70711C12.3166 5.31658 11.6834 5.31658 11.2929 5.70711L5.75 11.25C5.33579 11.6642 5.33579 12.3358 5.75 12.75C6.16421 13.1642 6.83579 13.1642 7.25 12.75L11.4343 8.56569C11.7467 8.25327 12.2533 8.25327 12.5657 8.56569Z" fill="currentColor"></path> </svg> </span> <!--end::Svg Icon--> </div> <!--begin::Javascript--> <script>var hostUrl = "/static/default/pc/";</script> <!--begin::Global Javascript Bundle(mandatory for all pages)--> <script src="/static/default/pc/plugins/global/plugins.bundle.js"></script> <script src="/static/default/pc/js/scripts.bundle.js"></script> <!--end::Global Javascript Bundle--> <!--end::Javascript--> </body> <!--end::Body--> </html>