美文网首页
Syndication Feed框架

Syndication Feed框架

作者: 大爷的二舅 | 来源:发表于2018-03-06 23:16 被阅读40次

Django提供了一个高级联合供稿生成框架,可以轻松创建RSS和Atom供稿。 RSS和Atom都是基于XML的格式,可以用来自动更新网站内容的提要。 在这里阅读更多关于RSS的信息,并在这里获取有关Atom的信息。

要创建任何联合供稿,您只需编写一个简短的Python类。 您可以根据需要创建尽可能多的Feed。 Django还附带了一个较低级别的Feed生成API。 如果您想要在Web上下文之外生成订阅源,或者使用其他某种更低级的方式生成订阅源,请使用此选项。

高级框架

概观

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

Feed类

Feed类是一个表示联合供稿的Python类。 馈送可以是简单的(例如,网站新闻馈送或显示博客的最新条目的基本馈送)或更复杂(例如,显示特定类别中的所有博客条目的馈送,其中类别是可变的)。 Feed类的子类django.contrib.syndication.views.Feed。 他们可以生活在你的代码库的任何地方。 Feed类的实例是可以在你的URLconf中使用的视图。

一个简单的例子

这个简单的例子来自一个假设的警察新闻网站,描述了最新的五个新闻项目的饲料:

from django.contrib.syndication.views import Feed
from django.core.urlresolvers 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])

要将URL连接到此Feed,请将Feed对象的实例放入URLconf中。 例如:

from django.conf.urls import url
from myproject.feeds import LatestEntriesFeed

urlpatterns = [
    # ...
    url(r'^latest/feed/$', LatestEntriesFeed()),
    # ...
]

注意:

  • Feed类的子类django.contrib.syndication.views.Feed。
  • 标题,链接和描述分别对应于标准RSS <title>,<link>和<description>元素。
  • items()简单地说就是一个方法,它返回应该作为<item>元素包含在Feed中的对象列表。 尽管此示例使用Django的对象关系映射返回NewsItem对象,但不必返回模型实例。 尽管您可以通过使用Django模型免费获得一些功能,但items()可以返回您想要的任何类型的对象。
  • 如果您要创建Atom feed而不是RSS feed,请设置字幕属性而不是描述属性。 例如,请参阅本章后面的发布Atom和RSS源。

有一件事是要做的。 在RSS feed中,每个<item>都有一个<title>,<link>和<description>。 我们需要告诉框架将哪些数据放入这些元素。

对于<title>和<description>的内容,Django会尝试在Feed类中调用方法item_title()和item_description()。 它们传递一个参数,item,它是对象本身。 这些是可选的; 默认情况下,对象的Unicode代表用于两者。

如果您想为标题或描述进行特殊格式化,可以使用Django模板。 它们的路径可以通过Feed类中的title_template和description_template属性来指定。 为每个项目呈现模板并传递两个模板上下文变量:

  • {{obj}} - 当前对象(您在item()中返回的任何对象之一)。
  • {{site}} - 代表当前网站的Django网站对象。 这对{{site.domain}}或{{site.name}}很有用。

请参阅下面使用说明模板的“复杂示例”。

如果您需要提供比前面提到的两个变量更多的信息,还可以将附加信息传递给标题和描述模板。 您可以在Feed子类中提供get_context_data方法的实现。 例如:

from mysite.models import Article
from django.contrib.syndication.views import Feed

class ArticlesFeed(Feed):
    title = "My articles"
    description_template = "feeds/articles.html"

    def items(self):
        return Article.objects.order_by('-pub_date')[:5]

    def get_context_data(self, **kwargs):
        context = super(ArticlesFeed, self).get_context_data(**kwargs)
        context['foo'] = 'bar'
        return context 

在模版中

Something about {{ foo }}: {{ obj.description }}

这个方法将被item()返回的列表中的每个项目调用一次,其中包含以下关键字参数:

  • item:当前item。 出于向后兼容性的原因,此上下文变量的名称是{{obj}}。

  • obj:get_object()返回的对象。 默认情况下,这不会暴露给模板以避免与{{obj}}混淆(参见上文),但是您可以在实现get_context_data()时使用它。

  • site:如上所述的当前网站。

  • request:当前请求。

get_context_data()的行为模仿通用视图的行为 - 您应该调用super()从父类中检索上下文数据,添加数据并返回修改过的字典。

要指定<link>的内容,您有两个选项。 对于items()中的每个item,Django首先尝试调用Feed类中的item_link()方法。 以类似于标题和说明的方式,它传递了一个参数 - item。 如果该方法不存在,Django会尝试对该对象执行get_absolute_url()方法。

get_absolute_url()和item_link()都应该以正常的Python字符串的形式返回item的URL。 与get_absolute_url()一样,item_link()的结果将直接包含在URL中,因此您需要负责在方法本身内进行所有必要的URL引用和转换为ASCII。

一个复杂的例子

该框架还通过参数支持更复杂的提要。 例如,一个网站可以提供针对城市中每个警察的近期犯罪的RSS源。 为每个警察创建一个单独的饲料班是愚蠢的; 这会违反DRY原则并将数据耦合到编程逻辑。

相反,联合框架允许您访问从您的URLconf传递的参数,以便提要可以根据Feed的URL中的信息输出项目。 警察击败饲料可以通过这样的URL访问:

  • /beats/613/rss/ – 返回最近feed613条犯罪记录.
  • /beats/1424/rss/ – 返回最近feed1424条犯罪记录.

这些可以与URLconf行匹配,例如:

url(r'^beats/(?P[0-9]+)/rss/$', BeatFeed()),

与视图一样,URL中的参数与请求对象一起被传递给get_object()方法。 以下是这些特定于节拍的提要的代码:

from django.contrib.syndication.views import FeedDoesNotExist
from django.shortcuts import get_object_or_404

class BeatFeed(Feed):
    description_template = 'feeds/beat_description.html'

    def get_object(self, request, beat_id):
        return get_object_or_404(Beat, pk=beat_id)

    def title(self, obj):
        return "Police beat central: Crimes for beat %s" % obj.beat

    def link(self, obj):
        return obj.get_absolute_url()

    def description(self, obj):
        return "Crimes recently reported in police beat %s" % obj.beat

    def items(self, obj):
        return Crime.objects.filter(beat=obj).order_by('-crime_date')[:30]

为了生成feed的<title>,<link>和<description>,Django使用title(),link()和description()方法。

在前面的例子中,它们是简单的字符串类属性,但这个例子说明它们可以是字符串或方法。 对于标题,链接和描述中的每一个,Django都遵循以下算法:

  1. 首先,它尝试调用一个方法,传递obj参数,其中obj是get_object()返回的对象。
  2. 否则,它会尝试调用一个没有参数的方法。
  3. 如果没有,它使用class属性。

还要注意,items()也遵循相同的算法 - 首先,它会尝试item(obj),然后item(),然后最后一个item类属性(应该是一个列表)。 我们正在使用项目描述的模板。 它可以非常简单:

   {{ obj.description }}

但是,您可以根据需要自由添加格式。 下面的ExampleFeed类提供了有关Feed类的方法和属性的完整文档。

指定Feed的类型

默认情况下,此框架中生成的供稿使用RSS 2.0。 要改变这一点,请向Feed类添加feed_type属性,如下所示:

from django.utils.feedgenerator import Atom1Feed

class MyFeed(Feed):
    feed_type = Atom1Feed 

请注意,您将feed_type设置为类对象,而不是实例。 目前可用的Feed类型是:

  • django.utils.feedgenerator.Rss201rev2Feed (RSS 2.01. Default.)
  • django.utils.feedgenerator.RssUserland091Feed (RSS 0.91.)
  • django.utils.feedgenerator.Atom1Feed (Atom 1.0.)
外壳

要指定附件(如用于创建Podcast Feed的附件),请使用item_enclosure_url,item_enclosure_length和item_enclosure_mime_type挂钩。有关使用示例,请参阅下面的ExampleFeed类。

语言

由联合框架创建的源自动包含适当的<language>标记(RSS 2.0)或xml:lang属性(Atom)。这直接来自您的LANGUAGE_CODE设置。

网址

链接方法/属性可以返回绝对路径(例如/ blog /)或具有完全限定的域和协议的URL(例如http://www.example.com/blog/)。如果链接不返回域,联合框架将根据您的SITE_ID设置插入当前站点的域。 Atom提要需要<link rel =“self”>来定义提要的当前位置。联合框架根据SITE_ID设置自动填充当前网站的域。

串联发布Atom和RSS源

一些开发人员喜欢提供他们的提要的Atom和RSS版本。使用Django很容易:只需创建Feed类的子类并将feed_type设置为不同的东西即可。然后更新你的URLconf以添加额外的版本。这里有一个完整的例子:

from django.contrib.syndication.views import Feed
from policebeat.models import NewsItem
from django.utils.feedgenerator import Atom1Feed

class RssSiteNewsFeed(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]

class AtomSiteNewsFeed(RssSiteNewsFeed):
    feed_type = Atom1Feed
    subtitle = RssSiteNewsFeed.description 

在此示例中,RSS提要使用描述,而Atom提要使用子标题。 这是因为Atom Feed不提供Feed级别的描述,但它们确实提供了子标题。 如果您在Feed类中提供了说明,则Django不会自动将其添加到子标题元素中,因为子标题和说明不一定是相同的东西。 相反,你应该定义一个子标题属性。

在上面的例子中,我们只需将Atom feeds字幕设置为RSS订阅源描述,因为它已经很短了。 和随附的URLconf:

from django.conf.urls import url
from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed

urlpatterns = [
    # ...
    url(r'^sitenews/rss/$', RssSiteNewsFeed()),
    url(r'^sitenews/atom/$', AtomSiteNewsFeed()),
    # ...
]

有关说明Feed类的所有可能属性和方法的示例,请参阅供稿类参考

低级框架

在幕后,高层次的RSS框架使用较低层框架来生成提要的XML。 该框架位于单个模块中:django / utils / feedgenerator.py。 您可以自行使用此框架,以生成较低级别的Feed。 您还可以创建自定义Feed生成器子类以用于feed_type Feed选项。

SyndicationFeed类
feedgenerator模块包含一个基类:

  • django.utils.feedgenerator.SyndicationFeed

和几个子类:

  • django.utils.feedgenerator.RssUserland091Feed
  • django.utils.feedgenerator.Rss201rev2Feed
  • django.utils.feedgenerator.Atom1Feed
    这三个类中的每一个都知道如何将某种类型的feed呈现为XML。 他们共享这个界面:
SyndicationFeed.init()

使用适用于整个Feed的元数据字典初始化Feed。 所需的关键字参数是:

  • title
  • link
  • description

还有其他一些可选的关键字:

  • language
  • author_email
  • author_name
  • author_link
  • subtitle
  • categories
  • feed_url
  • feed_copyright
  • feed_guid
  • ttl

您传递给init的任何额外关键字参数都将存储在self.feed中,以用于定制Feed生成器。 所有参数都应该是Unicode对象,但类别除外,它们应该是Unicode对象的序列。

SyndicationFeed.add_item()

使用给定参数向Feed添加item。

所需的关键字参数是:

  • title
  • link
  • description

可选的关键字参数是:

  • author_email

  • author_name

  • author_link

  • pubdate

  • comments

  • unique_id

  • enclosure

  • categories

  • item_copyright

  • ttl

  • updateddate

额外的关键字参数将被存储为自定义feed生成器。 所有的参数,如果给出,应该是Unicode对象,除了:

  • pubdate应该是一个Python日期时间对象。
  • updateddate应该是一个Python日期时间对象。
  • 外壳应该是django.utils.feedgenerator.Enclosure的一个实例。
  • 类别应该是一系列的Unicode对象。
SyndicationFeed.write()

将给定编码中的馈送输出到outfile,这是一个类似文件的对象。

SyndicationFeed.writeString()

以给定编码中的字符串形式返回提要。 例如,要创建一个Atom 1.0提要并将其打印到标准输出:

>>> from django.utils import feedgenerator
>>> from datetime import datetime
>>> f = feedgenerator.Atom1Feed(
...     title="My Weblog",
...     link="http://www.example.com/",
...     description="In which I write about what I ate today.",
...     language="en",
...     author_name="Myself",
...     feed_url="http://example.com/atom.xml")
>>> f.add_item(title="Hot dog today",
...     link="http://www.example.com/entries/1/",
...     pubdate=datetime.now(),
...     description="<p>Today I had a Vienna Beef hot dog. It was pink, plump and per\
fect.</p>")
>>> print(f.writeString('UTF-8'))
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
...
</feed>
自定义Feed生成器

如果您需要制作自定义Feed格式,那么您有几个选项。如果Feed格式是完全自定义的,那么您需要继承SyndicationFeed并完全替换write()和writeString()方法。但是,如果Feed格式是RSS或Atom的副产品(即GeoRSS,Apple的iTunes播客格式等),则您有更好的选择。

这些类型的提要通常会为底层格式添加额外的元素和/或属性,并且SyndicationFeed会调用一组方法来获取这些额外的属性。因此,您可以继承相应的Feed生成器类(Atom1Feed或Rss201rev2Feed)并扩展这些回调。他们是:

SyndicationFeed.root_attributes(self,)

返回要添加到根提要素(提要/通道)的属性字典。

SyndicationFeed.add_root_elements(self,handler)

回调在根Feed元素(feed / channel)中添加元素。处理程序是Python内置SAX库的XMLGenerator;您将调用其中的方法来添加到正在处理的XML文档中。

SyndicationFeed.item_attributes(self,item)

返回要添加到每个项目(item / entry)元素的属性字典。参数item是传递给SyndicationFeed.add_item()的所有数据的字典。

SyndicationFeed.add_item_elements(self,handler,item)

回调添加元素到每个项目(item / entry)元素。处理程序和项目如上所述。

如果您重写了这些方法中的任何一个,请确保调用超类方法,因为它们为每种提要格式添加了必需的元素。

例如,您可能会开始实施iTunes RSS Feed生成器,如下所示:

class iTunesFeed(Rss201rev2Feed):
  def root_attributes(self):
      attrs = super(iTunesFeed, self).root_attributes()
      attrs['xmlns:itunes'] =  
        'http://www.itunes.com/dtds/podcast-1.0.dtd'
      return attrs

  def add_root_elements(self, handler):
      super(iTunesFeed, self).add_root_elements(handler)
      handler.addQuickElement('itunes:explicit', 'clean')

很明显,要完成一个完整的自定义feed类还有很多工作要做,但上面的例子应该说明基本思想。

相关文章

  • Syndication Feed框架

    Django提供了一个高级联合供稿生成框架,可以轻松创建RSS和Atom供稿。 RSS和Atom都是基于XML的格...

  • Django + uwsgi + nginx + bootstr

    Django是一个全面型框架, 很多功能都可以直接找到, 对于RSS功能, 可以从其中的高层框架的聚合Feed框架...

  • Scrapy自定义导出器

    导出器在Scrapy框架中称为Feed exports,支持JSON、CSV、XML格式的输出,当需要将数据存储为...

  • 03-feed流细节详细解析

    图片流和feed流的区别: 图片流——以图片为主体 feed流——以内容为主体 feed英文有喂养的意思,feed...

  • Feed The Rat Privacy Policy

    Feed The Rat Privacy Policy Feed The Rat has adopted this...

  • Hadoop数据生命周期管理框架Apache Falcon简介

    Apache Falcon是一个开源的hadoop数据生命周期管理框架, 它提供了数据源 (Feed) 的管理服务...

  • 关于feed

    个正常的流程来完成一个feed,应该会有以下步骤: 准备feed->上传feed->feed的内容呈现->对单个f...

  • feed流设计介绍

    简介 Feed流是Feed + 流,Feed的本意是饲料,Feed流的本意就是有人一直在往一个地方投递新鲜的饲料,...

  • 2022-01-07

    I'm drying feed my head feed my soul So cynical

  • Feed

    手机里的内容 永远不间断 下拉刷新 Feed, feed 微博精彩 视频好看 朋友圈点赞好好玩 Feed, fee...

网友评论

      本文标题:Syndication Feed框架

      本文链接:https://www.haomeiwen.com/subject/khvkfftx.html