revision-up-to: | 8961 (1.0) |
---|
Django には高水準の配信フィード (syndication feed) 生成フレームワークがつい てきます。このフレームワークを使えば、 RSS 形式や Atom 形式のフィードを簡 単に生成できます。
ちょっとした Python クラスを書くだけで配信フィードを作成できます。フィード は好きな数だけ生成できます。
Django には低水準のフィード生成 API もついてきます。 Web コンテキストの外で フィードを作成したい場合や、低水準での操作が必要な場合に使ってください。
高水準のフィード生成フレームワークはビューで実現されていて、デフォルトでは /feeds/ にフックされています。 Django は URL の残りの部分 (/feeds/ 以後の部分) を使って、どのフィードを出力するかを決めます。
最新の開発版の Django を使っていないのなら、 sites フレームワークがインストー ルされていて、データベースのテーブルが生成されているか確認してください。 (詳しくは sites フレームワークのドキュメント を参照してください)。 sites への依存性は開発版の Django で変更され、現在で は配信フィードフレームワークは sites フレームワークに依存していません。
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}),
# ...
)
上の例では、二つのフィード:
を登録しています。
セットアップしたら、あとは 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]
注意:
まだやるべきことが残っています。 RSS フィード中では、 <item> には <title>, <link>, <description> といったエレメントがあります。 そこで、これらのエレメントにどのデータを入れるのかをフレームワークに教える 必要があります。
<title> や <description> の中身を指定するには、 feeds/latest_title.html または :file::feeds/latest_description.html という名前の Django テン プレート を作成します。 latest は URLconf 中に指定しておいた、フィードの slug です。 .html 拡張子 が必要なことに注意して下さい。 RSS システムはこれらのテンプレートを各 要素に対してレンダリングします。このとき、二つのテンプレートコンテキ スト変数を渡します:
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 でアクセス できるようになっています:
ここでは "beats" が slug になっています。配信フレームワークは slug より 後ろの URL 部分要素 (URL bit) を調べ (0613 や 1424)、それらの URL bit にどのような意味を与え、フィード公開する項目の選択にどう影響を及ぼさせ るかをユーザがフックで指定できるようにします。
例を挙げてわかりやすく説明しましょう。巡回区域単位のフィードを生成するコー ドは以下のようになります:
from django.contrib.syndication.feeds import FeedDoesNotExist
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 bit があることに気づき、 slug 以後の文 字列をスラッシュ ("/") で分割して、 Feed クラスの get_object() メソッドの引数に渡して呼び出します。上の例では、 bit は ['0613'] になります。リクエストが /rss/beats/0613/foo/bar/ であれば bit は ['0613', 'foo', 'bar'] です。
get_object() は指定された bit を使って適切な巡回区域を選 択する役割を担っています。上の場合では、 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/ を処理させる方法が あります。それは、 bits が空のリストのときです。上の例では、 len(bits) !=1 のとき、 ObjectDoesNotExist 例外を送出する ので、 /rss/beats/ は 404 エラーページを生成します。しかし、 実際にはここで好きな処理を行って構いません。たとえば、全ての beat の フィードを合わせたような結果を生成して返してもよいのです。
フィードの <title>, <link>, および <description> を生成す るために、 Django はそれぞれ title(), link() および description() といったメソッドを使います。こうしたメソッドは 前述の例では単なる文字列でできたクラス属性でしたが、実際には文字列に もメソッドにもできます。 title, link および description については、 Django は以下のようなアルゴリズムで値を決めます:
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 つです:
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 オプションに指定して使えます。
feedgenerator モジュールには、ベースクラス:
と、以下のサブクラスが定義されています:
これらのクラスはいずれも、特定のタイプの XML を生成する方法を知っており、 以下のような共通のインタフェースを持っています:
メタデータの入った辞書をもとにフィードを生成します。メタデータはフィー ド全体に適用されます。以下の引数が必須です:
また、以下のようなオプションキーワードをサポートしています:
これ以外のキーワード引数を __init__ に渡すと、 self.feed に保存 されます。使い方は カスタムのフィードジェネレータ を参照してく ださい。
パラメタは全て Unicode オブジェクトで指定します。ただし、 categories は Unicode オブジェクトのリストです。
指定のパラメタをもった項目をフィードに追加します。
以下の引数は必須です:
また、以下のオプションの引数があります:
それ以外のキーワード引数は カスタムのフィードジェネレータ 用に保存され ます。
パラメタには Unicode オブジェクトを指定します。ただし:
以下の例では 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) をサブクラス化して、コールバックを拡張すればよいのです。 拡張用のメソッドを以下に示します:
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')
もちろん、カスタムのフィードクラスを定義するには他にもたくさん作業が必要で すが、上の例を見れば基本的な考え方は理解できるはずです。
Aug 31, 2012