revision-up-to: | 11321 (1.1) |
---|
Django には高水準の配信フィード (syndication feed) 生成フレームワークがつい てきます。このフレームワークを使えば、 RSS 形式や Atom 形式のフィードを簡 単に生成できます。
配信フィードの作成は、ちょっとした Python クラスを書くだけでできます。フィー ドは好きな数だけ生成できます。
Django には低水準のフィード生成 API もついてきます。 Web コンテキストの外で フィードを作成したい場合や、低水準での操作が必要な場合に使ってください。
高水準のフィード生成フレームワークはビューで実現されていて、デフォルトでは
/feeds/
にフックされています。 Django は URL の残りの部分 (/feeds/
以後の部分) を使って、どのフィードを出力するかを決めます。
Django サイトで配信フィードを使うには、 URLConf に以下のような行を追加します:
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),
この行は、 Django に "feeds/"
で始まる全ての URL を RSS フレームワー
クで処理するように教えます (もちろん "feeds/"
は自分の好きなプレフィ
クスに置き換えられます)。
上の URLconf には追加の引数、 {'feed_dict': feeds}
があります。この引数
は、URL に対してどのクラスを使ってフィード生成を行うかを配信フレームワーク
に教えます。
特に、 feed_dict
はフィードの slug (短い URL ラベル) を
Feed
クラスに対応づける辞書でな
くてはなりません。
feed_dict
は URLconf の中で定義できます。 URLconf の完全な例を示しましょ
う:
from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory
feeds = {
'latest': LatestEntries,
'categories': LatestEntriesByCategory,
}
urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)
上の例では、二つのフィード:
feeds/latest/
にある、LatestEntries
で表されるフィードfeeds/categories/
にある、LatestEntriesByCategory
で表され るフィード
を登録しています。
セットアップしたら、あとは Feed
クラス自体を定義するだけです。
Feed
クラスは、ひとつの配信フィー
ドを表現する単純な Python クラスです。フィードは単純な形式 (「サイトニュー
ス」フィードや、最新のブログエントリを表示する基本的な形式 ) にも、もっと複
雑な形式 (特定のカテゴリの全てのエントリを表示するフィード) にもできます。
Feed
クラスは
django.contrib.syndication.feeds.Feed
のサブクラスにせねばなりませ
ん。クラスはコードベースのどこにでも置けます。
以下の例は chicagocrime.org で使っているもので、最新の 5 件のニュース項 目を記述するようになっています:
from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem
class LatestEntries(Feed):
title = "Chicagocrime.org site news"
link = "/sitenews/"
description = "Updates on changes and additions to chicagocrime.org."
def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]
注意:
django.contrib.syndication.feeds.Feed
のサブクラスになっています。title
, link
および description
は、それぞれ標準的
な RSS の <title>
, <link>
および <description>
要素に対応して
います。items()
はフィードの <item>
要素に含めるオブジェクトのリスト
を返すメソッドです。この例では Django の
Object-Relational マッパ を使って
NewsItem
を返していますが、 items()
は必ずしもモデルインスタ
ンスを返さねばならないわけではありません。 Django モデルを使えばいくつか
の機能を何もせずに使えるというだけの話で、 items()
は望みのどんな
型のオブジェクトを返してもかまいません。description
属性の代わりに subtitle
属性を設定してください。詳しくは
Atom フィードと RSS フィードを並行出力する
を参照してください。まだやるべきことが残っています。 RSS フィード中では、 <item>
には
<title>
, <link>
, <description>
といったエレメントがあります。
そこで、これらのエレメントにどのデータを入れるのかをフレームワークに教える
必要があります。
<title>
や<description>
の中身を指定するには、feeds/latest_title.html
またはfeeds/latest_description.html
という名前の Django テン プレート を作成します。latest
は URLconf 中に指定しておいた、フィードのslug
です。.html
拡張子 が必要なことに注意して下さい。 RSS システムはこれらのテンプレートを各 要素に対してレンダリングします。このとき、二つのテンプレートコンテキ スト変数を渡します:
{{ obj }}
– 現在のオブジェクト (items()
の返すオブ ジェクトの中の一つ) です。{{ site }}
– 現在のサイトを表現する、django.contrib.sites.models.Site
オブジェクトです。この変数 は{{ site.domain }}
や{{ site.name }}
を参照する際に 便利です。最新の開発版の Django を使っていて、 sites フレームワー クを 使っていない 場合、この値はdjango.contrib.sites.models.RequestSite
オブジェクトになり ます。詳しくは RequestSite の説明 を参照してください。
title
やdescription
のテンプレートを作成しなかった場合、 RSS フレームワークは"{{ obj }}"
で表されるテンプレートをデフォルト値 として使います。すなわち、オブジェクトの文字列表現が使われます。Feed
クラスにtitle_template
やdescription_template
といった属性値を指定す れば、これらのテンプレートの名前を指定できます。
<link>
の内容を指定するには二つの方法があります。items()
の各要素毎に、Django はまずオブジェクトに対してget_absolute_url()
メソッドを実行しようと試みます。このメソッドが なければ、Feed
クラスで定 義されているitem_link()
メソッドを呼び出そうとします。このと き、メソッドにはオブジェクト自体を引数item
として渡します。get_absolute_url()
やitem_link()
は、いずれも通常の Python 文字列で URL を返さねばなりません。また、get_absolute_url()
と同様、item_link()
の返す値は直接 URL に組み込めなければなりません。このため、プログラマは、必要に応じ て URL のクオート処理や変換を行って、全ての文字が ASCII 文字からなる 値に変換する責任があります。上の LatestEntries の例では、以下のような簡単なフィードテンプレートに できます:
* latest_title.html:{{ obj.title }}
latest_description.html:
{{ obj.description }}
配信フレームワークは、パラメタを使ったより複雑なフィードをサポートしています。
例えば、 chicagocrime.org では、シカゴ市内の全ての警官の巡回区域 (beat)
ごとに最新の犯罪情報のフィードを提供しています。全ての巡回区域毎に
Feed
クラスを用意するのは馬鹿ら
しい話です。 DRY 則 に反していますし、データの都合とプログラム
ロジックを連結させてしまうことになります。その代わりに、配信フレームワーク
では、フィードの URL に指定した情報に従って適切な要素を出力するような汎用の
フィードを生成できるようにしています。
chicagocrime.org では、巡回区域単位のフィードに以下のような URL でアクセス できるようになっています:
/rss/beats/0613/
– 0613 区の最近の犯罪を返します。/rss/beats/1424/
– 1424 区の最近の犯罪を返します。
ここでは "beats"
が slug になっています。配信フレームワークは slug より
後ろの URL 部分要素 (URL bit) を調べ (0613
や 1424
)、それらの URL
bit にどのような意味を与え、フィード公開する項目の選択にどう影響を及ぼさせ
るかをユーザがフックで指定できるようにします。
例を挙げてわかりやすく説明しましょう。巡回区域単位のフィードを生成するコー ドは以下のようになります:
from django.contrib.syndication.feeds import FeedDoesNotExist
from django.core.exceptions import ObjectDoesNotExist
class BeatFeed(Feed):
def get_object(self, bits):
# In case of "/rss/beats/0613/foo/bar/baz/", or other such clutter,
# check that bits has only one member.
if len(bits) != 1:
raise ObjectDoesNotExist
return Beat.objects.get(beat__exact=bits[0])
def title(self, obj):
return "Chicagocrime.org: Crimes for beat %s" % obj.beat
def link(self, obj):
if not obj:
raise FeedDoesNotExist
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__id__exact=obj.id).order_by('-crime_date')[:30]
このクラスに URL /rss/beats/0613/
でアクセスしたときの、 RSS フレー
ムワークの基本的なアルゴリズムは以下の通りです:
フレームワークに URL
/rss/beats/0613/
が渡されます。フレーム ワークは slug 以後の URL 部分を検出し、 slug 以後の文字列をスラッシュ ("/"
) で分割して、Feed
クラスのget_object()
メソッドの引数bits
に渡して呼び出します。上 の例ではbits
は['0613']
になります。リクエストが/rss/beats/0613/foo/bar/
であればbits
は['0613', 'foo', 'bar']
です。
get_object()
は指定されたbits
を使って適切な巡回区域を選 択する役割を担っています。上の場合では、 Django のデータベース API を 使って巡回区域を決定しています。 無効なパラメタが指定された場合、get_object()
はdjango.core.exceptions.ObjectDoesNotExist
を返さねばなりません。 関数が失敗するとBeat.DoesNotExist
を送出し、Beat.DoesNotExist
はObjectDoesNotExist
のサブクラスなので、Beat.objects.get()
呼び出しの周りにはtry
/except
がありま せん。get_object()
の中でObjectDoesNotExist
を送出すると、 Django はリクエストに対して 404 エラーを返します。get_object()
で/rss/beats/
を扱えるようになりまし た。
get_object()
を使って/rss/beats/
を処理させる方法が あります。それは、bits
が空のリストのときです。上の例では、len(bits) !=1
のとき、ObjectDoesNotExist
例外を送出する ので、/rss/beats/
は 404 エラーページを生成します。しかし、 実際にはここで好きな処理を行って構いません。たとえば、全ての beat の フィードを合わせたような結果を生成して返してもよいのです。フィードの
<title>
,<link>
, および<description>
を生成す るために、 Django はそれぞれtitle()
,link()
およびdescription()
といったメソッドを使います。こうしたメソッドは 前述の例では単なる文字列でできたクラス属性でしたが、実際には文字列に もメソッドにもできます。title
,link
およびdescription
については、 Django は以下のようなアルゴリズムで値を決めます:
get_object()
の返すオブジェクトobj
を引数にして、メ ソッドを呼び出そうと試みます。- 失敗した場合、メソッドを引数無しで呼び出そうと試みます。
- 失敗した場合、クラス属性を使います。
link()
メソッドの中では、obj
がNone
の場合、すなわ ちURL が完全に指定されなかった場合の処理を定義しておかねばなりません。 この部分で、obj
が存在するかどうかチェックしない場合には、他のメ ソッドでも、obj
がNone
であるかチェックする必要があるでしょ う (link()
メソッドは、フィード生成プロセスのきわめて初期段階 で呼び出されるので、例外ではじき出しておくのにいい場所です)。最後に、上の例の
items()
には引数obj
があることに注意し て下さい。items
の内容を解決するアルゴリズムは上と同じです。 すなわち、まずitems(obj)
, 次いでitems()
, そしてクラ ス属性items`
(この値はリストでなければなりません) の順です。
下記の ExampleFeed
クラスには、
Feed
クラスの全てのメソッドと属
性についてのドキュメントが書かれています。
このフレームワークは、デフォルトでは RSS 2.0 のフィードを生成します。
生成するフィードの形式を変えたければ、
Feed
クラスの feed_type
属性
を変更します:
from django.utils.feedgenerator import Atom1Feed
class MyFeed(Feed):
feed_type = Atom1Feed
feed_type
にはインスタンスではなくクラスオブジェクトを指定するよう注意
して下さい。
現在利用可能なフィードの型は以下の 3 つです:
django.utils.feedgenerator.Rss201rev2Feed
(RSS 2.01、デフォ ルトの形式。)django.utils.feedgenerator.RssUserland091Feed
(RSS 0.91 形式。)django.utils.feedgenerator.Atom1Feed
(Atom 1.0 形式。)
podcast のフィードを生成するときなどに使われるエンクロージャ (enclusure) の
指定には、 item_enclosure_url
, item_enclosure_length
および
item_enclosure_mime_type
フックを使って下さい。後述の使用例にある
ExampleFeed
クラスを参照してください。
配信フレームワークによって生成されたフィードには、自動的に適切な
<language>
タグ (RSS 2.0) や xml:lang
属性 (Atom) が入ります。
これらの値には LANGUAGE_CODE
を直接使います。
link
メソッド/属性は絶対 URL (すなわち "/blog/"
) またはドメイン
やプロトコルを完全指定した URL ("http://www.example.com/blog/"
) のいず
れかを返さねばなりません。 link
がドメインを返さない場合、配信フレー
ムワークは現在のサイトのドメインを SITE_ID
に従って挿
入します。
Atom フィードにはフィードの現在の場所を定義する <link rel="self">
が必
要です。配信フレームワークは現在の SITE_ID の設定に従ってドメインから取り出
した値を自動的に入れるようになっています。
Atom と RSS の 両方の バージョンを利用したい開発者もいることでしょう。
Django を使えば簡単に実現できます。自作の
Feed
クラスをサブクラス化して、
feed_type
を変更し、 URLconf を更新して、他のバージョン向けのエント
リを追加するだけです。
完全な例を示しましょう:
from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem
from django.utils.feedgenerator import Atom1Feed
class RssSiteNewsFeed(Feed):
title = "Chicagocrime.org site news"
link = "/sitenews/"
description = "Updates on changes and additions to chicagocrime.org."
def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]
class AtomSiteNewsFeed(RssSiteNewsFeed):
feed_type = Atom1Feed
subtitle = RssSiteNewsFeed.description
Note
上の例では、RSS フィードは description
を使っています。一方、
Atom フィードでは subtitle
を使っています。Atom フィードはフィー
ドレベルの description
を持たず、 subtitle
を持っている
からです。
Feed
クラスに
description
を定義しておいても、Django は description
の値を自動的に subtitle
エレメントに入れたりはしません。
subtitle
と description
は必ずしも同じものを指さないか
らです。その代わり、適切な説明の入った文字列をモデルの subtitle
属性として指定せねばなりません。
上の例では、たまたま RSS フィードの description
は十分短いので、
そのまま使っています。
対応する URLconf は以下のようにします:
from django.conf.urls.defaults import *
from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed
feeds = {
'rss': RssSiteNewsFeed,
'atom': AtomSiteNewsFeed,
}
urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)
この節の例では、 Feed
クラスで利
用できる全ての属性とメソッドについて説明しています:
from django.contrib.syndication.feeds import Feed
from django.utils import feedgenerator
class ExampleFeed(Feed):
# FEED TYPE -- 省略可能です。
# django.utils.feedgenerator.SyndicationFeed のサブクラスを
# 指定せねばなりません。 RSS 2.0, Atom 1.0 といったフィードの形式
# を表します。
# feed_type を指定しなければ、 RSS 2.0 を使います。
# クラスのインスタンスではなく、クラス自体にせねばなりません。
feed_type = feedgenerator.Rss201rev2Feed
# TEMPLATE NAMES -- 省略可能です。
# フィード項目のタイトルと詳細をレンダリングするための Django テン
# プレート名を表す名前でなければなりません。いずれも省略可能です。
# 片方、または両方を省略した場合、 Django は
# 'feeds/SLUG_title.html' および 'feeds/SLUG_description.html' とい
# う名前のテンプレートを使います。 SLUG は URL に指定した slug です。
title_template = None
description_template = None
# TITLE -- 以下の三つの形式の少なくともいずれか一つが必要です。配信
# フレームワークは以下の順に値を探します。
def title(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、フィードのタイトルを
通常の python 文字列で返します。
"""
def title(self):
"""
フィードのタイトルを通常の python 文字列で返します。
"""
title = 'foo' # ハードコード形式のフィードのタイトルです。
# LINK -- 以下の三つの形式の少なくともいずれか一つが必要です。配信
# フレームワークは以下の順に値を探します。
def link(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、フィードへのリンクを
通常の python 文字列で返します。
"""
def link(self):
"""
フィードへのリンクを通常の python 文字列で返します。
"""
link = '/foo/bar/' # ハードコード形式のフィードのリンクです。
# GUID -- 省略可能です。配信フレームワークは以下の順に値を探します。
# このプロパティは Atom フィード (のフィードレベルの ID エレメント)
# でしか使いません。省略すると、フィードのリンクを ID に使います。
def feed_guid(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、一意なフィードの識
別子を Python 文字列として返します。
"""
def feed_guid(self):
"""
一意なフィードの識別子を Python 文字列として返します。
"""
feed_guid = '/foo/bar/1234' # ハードコード形式の guid です。
# DESCRIPTION -- 以下の三つの形式の少なくともいずれか一つが必要です。
# 配信フレームワークは以下の順に値を探します。
def description(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、フィードの説明
を通常の python 文字列で返します。
"""
def description(self):
"""
フィードの説明を通常の python 文字列で返します。
"""
description = 'Foo bar baz.' # ハードコード形式のフィードの説明です。
# AUTHOR NAME -- 以下の三つの形式のいずれか一つを指定できます。配信
# フレームワークは以下の順に値を探します。省略可能です。
def author_name(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、フィードの作者名を
通常の python 文字列で返します。
"""
def author_name(self):
"""
フィードの作者名を通常の python 文字列で返します。
"""
author_name = 'Sally Smith' # ハードコード形式のフィードの作者名です。
# AUTHOR E-MAIL -- 以下の三つの形式のいずれか一つを指定できます。配信
# フレームワークは以下の順に値を探します。省略可能です。
def author_email(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、フィードの作者の email を
通常の python 文字列で返します。
"""
def author_name(self):
"""
フィードの作者の email を通常の python 文字列で返します。
"""
author_email = 'test@example.com' # ハードコード形式の作者の email です。
# AUTHOR LINK -- 以下の三つの形式のいずれか一つを指定できます。配信
# フレームワークは以下の順に値を探します。省略可能です。どの場合でも、
# URL には "http://" およびドメイン名を入れねばなりません。
def author_link(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、フィードの作者の
URL を通常の python 文字列で返します。
"""
def author_link(self):
"""
フィードの作者の URL を通常の python 文字列で返します。
"""
author_link = 'http://www.example.com/' # ハードコード形式の作者 URL です。
# CATEGORIES -- 以下の三つの形式はいずれも省略可能です。フレームワー
# クは以下に示した順番で値を探します。いずれの場合も、メソッド/属性
# 値は文字列を返すイテレータを返さねばなりません。
def categories(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、フィードのカテゴリ
を表す文字列を返すイテレータを返します。
"""
def categories(self):
"""
フィードのカテゴリを表す文字列を返すイテレータを返します。
"""
# カテゴリリストのハードコード表現です。
categories = ("python", "django")
# COPYRIGHT NOTICE -- 以下の三つの形式はいずれも省略可能です。
# フレームワークは以下に示した順番で値を探します。
def copyright(self, obj):
"""
get_object() が返すようなオブジェクトを引数 obj にとり、
フィードの著作権表示を通常の Python 文字列型で返します。
"""
def copyright(self):
"""
フィードの著作権表示を通常の Python 文字列型で返します。
"""
# 著作権表示のハードコード表現です。
copyright = 'Copyright (c) 2007, Sally Smith'
# TTL -- 以下の三つの形式はいずれも省略可能です。
# フレームワークは以下に示した順番で値を探します。
# Atom フィードでは無視されます。
def ttl(self, obj):
"""
get_object() が返すようなオブジェクトを引数 obj にとり、
フィードの TTL (寿命) を 通常の Python 文字列型で返します。
"""
def ttl(self):
"""
フィードの TTL (寿命) を 通常の Python 文字列型で返します。
"""
ttl = 600 # TTL のハードコード表現です。
# ITEMS -- 以下の三つの形式の少なくともいずれか一つが必要です。配信
# フレームワークは以下の順に値を探します。
def items(self, obj):
"""
get_object() の返すオブジェクトを引数にとり、このフィードで公
開する item のリストを返します。
"""
def items(self):
"""
フィードで公開する item のリストを返します。
"""
items = ('Item 1', 'Item 2') # ハードコード形式の item リストです。
# GET_OBJECT -- 異なる URL パラメタに対して異なるデータを公開する場
# 合に必要なメソッドです。 (前述の "複雑な例" を参照してください)
def get(self, bits):
"""
URL から取り出した文字列のリストを引数にとり、フィードで表現す
るオブジェクトからなるリストを返します。エラー時には
django.core.exceptions.ObjectDoesNotExist を送出します。
"""
# ITEM LINK -- 以下の三つの形式の少なくともいずれか一つが必要です。配信
# フレームワークは以下の順に値を探します。
# まず、フレームワークは以下の二つのメソッドを順に試します。失敗す
# ると、 items() の返す各オブジェクトに対して get_absolute_url() を
# 呼び出します。
def item_link(self, item):
"""
items() の返す item を引数に取り、item への URL を返します。
"""
def item_link(self):
"""
item への URL を返します。
"""
# ITEM_GUID -- 以下のメソッドは省略可能です。
# このプロパティは Atom フィード (のフィードレベルの ID エレメント)
# でしか使いません。省略すると、item のリンクを ID に使います。
def item_guid(self, obj):
"""
items() の返す item を引数にとり、 item の ID を返します。
"""
# ITEM AUTHOR NAME -- 以下の三つの形式のいずれか一つを指定できます。配信
# フレームワークは以下の順に値を探します。省略可能です。
def item_author_name(self, item):
"""
items() の返す item を引数に取り、item の作者名を通常の python
文字列で返します。
"""
def item_author_name(self):
"""
作者名を返します。
"""
item_author_name = 'Sally Smith' # ハードコード形式の作者名です。
# ITEM AUTHOR E-MAIL -- 以下の三つの形式のいずれか一つを指定できます。配信
# フレームワークは以下の順に値を探します。省略可能です。
#
# この属性を指定する場合、item_author_name も指定せねばなりません。
def item_author_email(self, obj):
"""
items() の返す item を引数に取り、item の作者の e-mail を通常の
python 文字列で返します。
"""
def item_author_email(self):
"""
作者の e-mail を返します。
"""
item_author_email = 'test@example.com' # ハードコード形式の作者 e-mail です。
# ITEM AUTHOR LINK -- 以下の三つの形式のいずれか一つを指定できます。配信
# フレームワークは以下の順に値を探します。省略可能です。この場合、
# URL には "http://" およびドメイン名を入れねばなりません。
#
# この属性を指定する場合、 item_author_name も指定せねばなりません。
def item_author_link(self, obj):
"""
items() の返す item を引数に取り、item の作者の URL を通常の
python 文字列で返します。
"""
def item_author_link(self):
"""
item の作者の URL を通常の python 文字列で返します。
"""
item_author_link = 'http://www.example.com/' # ハードコード形式の作者 URL です。
# ITEM ENCLOSURE URL -- エンクロージャを公開する場合、以下の三つの
# 形式の少なくともいずれか一つが必要です。配信フレームワークは以下
# の順に値を探します。
def item_enclosure_url(self, item):
"""
items() の返す item を引数に取り、item のエンクロージャ URL を返します。
"""
def item_enclosure_url(self):
"""
フィード中の各 item のエンクロージャ URL を返します。
"""
item_enclosure_url = "/foo/bar.mp3" # ハードコード形式のエンクロージャ URL です。
# ITEM ENCLOSURE LENGTH -- エンクロージャを公開する場合、以下の三つ
# の形式の少なくともいずれか一つが必要です。配信フレームワークは以
# 下の順に値を探します。この場合、戻り値はバイト単位で長さを表した
# 整数か、整数を表す文字列でなければなりません。
def item_enclosure_length(self, item):
"""
items() の返す item を引数に取り、item のエンクロージャ長を返します。
"""
def item_enclosure_length(self):
"""
フィード中の各 item のエンクロージャ長を返します。
"""
item_enclosure_length = 32000 # ハードコード形式のエンクロージャ長です。
# ITEM ENCLOSURE MIME TYPE -- エンクロージャを公開する場合、以下の
# 三つの形式の少なくともいずれか一つが必要です。配信フレームワーク
# は以下の順に値を探します。
def item_enclosure_mime_type(self, item):
"""
items() の返す item を引数に取り、item のエンクロージャ MIME タ
イプを返します。
"""
def item_enclosure_mime_type(self):
"""
各 item のエンクロージャの MIME タイプを返します。
"""
item_enclosure_mime_type = "audio/mpeg" # ハードコード形式の MIME
# タイプです。
# ITEM PUBDATE -- 以下の三つの形式のいずれか一つを指定できます。
# 省略可能です。
# このメソッドは指定の要素に対する公開日を取得するためのフックです。
# どのケースでも、メソッドや属性は Python の datetime.datetime
# オブジェクトを返さねばなりません。
def item_pubdate(self, item):
"""
items() の返す item を引数に取り、item の公開日を返します。
"""
def item_pubdate(self):
"""
公開日を返します。
"""
item_pubdate = datetime.datetime(2005, 5, 3) # ハードコード形式の公開日です。
# ITEM CATEGORIES -- 以下の三つの形式はいずれも省略可能です。指定さ
# れた item に対するカテゴリリストを取得するためのフックです。いずれ
# の場合も、メソッド/属性値は文字列を返すイテレータを返さねばなりま
# せん。
def item_categories(self, item):
"""
items() の返す item を引数にとり、 item のカテゴリ
を表す文字列を返すイテレータを返します。
"""
def item_categories(self):
"""
フィード内の全 items のカテゴリを返します。
"""
item_categories = ("python", "django") # ハードコード形式のカテゴリです。
# ITEM COPYRIGHT NOTICE (Atom フィードにのみ適用されます)
# 以下の三つの形式のいずれか一つを指定できます。配信フレームワーク
# は以下の順に値を探します。省略可能です。
def item_copyright(self, obj):
"""
items() の返す item を引数にとり、 item の著作権表示を
通常の Python 文字列型で返します。
"""
def item_copyright(self):
"""
全 item の著作権表示を通常の Python 文字列型で返します。
"""
# 著作権表示をハードコードする場合の指定方法です。
item_copyright = 'Copyright (c) 2007, Sally Smith'
高水準の RSS フレームワークは、背後で低水準のフレームワークを使ってフィード の XML を生成しています。このフレームワーク自体は、 django/utils/feedgenerator.py に単一のモジュールとして収められています。
このフレームワークを使って、自分で低水準のフィード生成処理を実装できます。
また、フィードジェネレータのサブクラスを作成すれば、 Feed
の
feed_type
オプションに指定して使えます。
SyndicationFeed
クラス¶feedgenerator
モジュールには、ベースクラス:
と、以下のサブクラスが定義されています:
これらのクラスはいずれも、特定のタイプの XML を生成する方法を知っており、 以下のような共通のインタフェースを持っています:
メタデータの入った辞書をもとにフィードを生成します。メタデータはフィー ド全体に適用されます。以下の引数が必須です:
title
link
description
また、以下のようなオプションキーワードをサポートしています:
language
author_email
author_name
author_link
subtitle
categories
feed_url
feed_copyright
feed_guid
ttl
これ以外のキーワード引数を __init__
に渡すと、 self.feed
に保存
されます。使い方は
カスタムのフィードジェネレータ を参照してください。
パラメタは全て Unicode オブジェクトで指定します。ただし、
categories
は Unicode オブジェクトのリストです。
指定のパラメタをもった項目をフィードに追加します。
以下の引数は必須です:
title
link
description
また、以下のオプションの引数があります:
author_email
author_name
author_link
pubdate
comments
unique_id
enclosure
categories
item_copyright
ttl
それ以外のキーワード引数は カスタムのフィードジェネレータ 用に保存されます。
パラメタには Unicode オブジェクトを指定します。ただし:
pubdate
は Python datetime 型オブジェクト にします。enclosure
はfeedgenerator.Enclosure
のインスタンスにします。categories
は Unicode オブジェクトのシークエンスにします。
フィードを指定のエンコーディングでファイルライクオブジェクト outfile に 出力します。
フィードを指定のエンコーディングの文字列として返します。
以下の例では Atom 1.0 フィードを生成して、標準出力に出力しています:
>>> from django.utils import feedgenerator
>>> f = feedgenerator.Atom1Feed(
... title=u"My Weblog",
... link=u"http://www.example.com/",
... description=u"In which I write about what I ate today.",
... language=u"en")
>>> f.add_item(title=u"Hot dog today",
... link=u"http://www.example.com/entries/1/",
... description=u"<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>")
>>> print f.writeString('utf8')
<?xml version="1.0" encoding="utf8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
...
</feed>
カスタムのフォーマットでフィードを生成したいなら、二つ方法があります。
完全に独自の形式のフィードなら、 SyndicationFeed
をサブクラス化して、
write()
および writeString()
メソッドを完全に書き直すとよいでしょう。
しかし、 (GeoRSS や Apple の iTunes podcast フォーマット )のように、既
存のフィードフォーマットから派生したものであれば、もっといい選択肢がありま
す。この手の派生フォーマットは、元のフォーマットにエレメントや属性を追加し
ていて、 SyndicationFeed
のメソッドには、こうした追加の属性を取得するた
めのものがあります。ですから、適切なフィードクラス (Atom1Feed
や
Rss201rev2Feed
) をサブクラス化して、コールバックを拡張すればよいのです。
拡張用のメソッドを以下に示します:
SyndicationFeed.root_attributes(self, )
feed
/channel
) に追加する属性の入った
dict
を返します。SyndicationFeed.add_root_elements(self, handler)
feed
/channel
) 要素に新たに要素を付加する
ためのコールバックです。 handler
は Python 組み込み SAX ライブラリ
の XMLGenerator です。このオブジェクトのメソッドを呼び出して、 処理中
の XML ドキュメントに要素を追加します。SyndicationFeed.item_attributes(self, item)
item
/entry
) に追加する属性の入った dict
を返します。引数 item
は、 SyndicationFeed.item()
に渡された
データの入っている dict
です。SyndicationFeed.add_item_elements(self, handler, item)
item
/entry
) 要素に新たに要素を付加するためのコールバッ
クです。 handler
と item
は上と同じです。Warning
これらのメソッドをオーバライドするときは、スーパクラスのメソッドを忘れ ずに呼び出してください。スーパクラス側でも、必須の要素を追加するために これらのメソッドを使っているからです。
例えば、 iTunes RSS フィードジェネレータを実装するなら、書き始めは以下のよ うになるでしょう:
class iTunesFeed(Rss201rev2Feed):
def root_attibutes(self):
attrs = super(iTunesFeed, self).root_attibutes()
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')
もちろん、カスタムのフィードクラスを定義するには他にもたくさん作業が必要で すが、上の例を見れば基本的な考え方は理解できるはずです。
Oct 26, 2017