.. _ref-contrib-syndication: ========================== 配信フィードフレームワーク ========================== :revision-up-to: 11321 (1.1) .. module:: django.contrib.syndication :synopsis: RSS や Atom 形式の配信フィードを簡単に生成するためのフレーム ワークです。 Django には高水準の配信フィード (syndication feed) 生成フレームワークがつい てきます。このフレームワークを使えば、 RSS_ 形式や Atom_ 形式のフィードを簡 単に生成できます。 配信フィードの作成は、ちょっとした Python クラスを書くだけでできます。フィー ドは好きな数だけ生成できます。 Django には低水準のフィード生成 API もついてきます。 Web コンテキストの外で フィードを作成したい場合や、低水準での操作が必要な場合に使ってください。 .. _RSS: http://www.whatisrss.com/ .. _Atom: http://www.atomenabled.org/ 高水準フレームワーク ==================== 概要 ---- 高水準のフィード生成フレームワークはビューで実現されていて、デフォルトでは ``/feeds/`` にフックされています。 Django は URL の残りの部分 (``/feeds/`` 以後の部分) を使って、どのフィードを出力するかを決めます。 フィードを生成するには、 :class:`~django.contrib.syndication.feeds.Feed` ク ラスを書き、 :ref:`URLConf ` 内で指定します。 初期化 -------------- Django サイトで配信フィードを使うには、 :ref:`URLConf ` に以下のような行を追加します:: (r'^feeds/(?P.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}), この行は、 Django に :file:`"feeds/"` で始まる全ての URL を RSS フレームワー クで処理するように教えます (もちろん :file:`"feeds/"` は自分の好きなプレフィ クスに置き換えられます)。 上の URLconf には追加の引数、 ``{'feed_dict': feeds}`` があります。この引数 は、URL に対してどのクラスを使ってフィード生成を行うかを配信フレームワーク に教えます。 特に、 :data:`feed_dict` はフィードの slug (短い URL ラベル) を :class:`~django.contrib.syndication.feeds.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.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}), # ... ) 上の例では、二つのフィード: * ``feeds/latest/`` にある、 ``LatestEntries`` で表されるフィード * ``feeds/categories/`` にある、 ``LatestEntriesByCategory`` で表され るフィード を登録しています。 セットアップしたら、あとは :class:`~django.contrib.syndication.feeds.Feed` クラス自体を定義するだけです。 Feed クラス ------------ :class:`~django.contrib.syndication.feeds.Feed` クラスは、ひとつの配信フィー ドを表現する単純な Python クラスです。フィードは単純な形式 (「サイトニュー ス」フィードや、最新のブログエントリを表示する基本的な形式 ) にも、もっと複 雑な形式 (特定のカテゴリの全てのエントリを表示するフィード) にもできます。 :class:`~django.contrib.syndication.feeds.Feed` クラスは :class:`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`` のサブクラスになっています。 * :attr:`title`, :attr:`link` および :attr:`description` は、それぞれ標準的 な RSS の ````, ``<link>`` および ``<description>`` 要素に対応して います。 * :meth:`items()` はフィードの ``<item>`` 要素に含めるオブジェクトのリスト を返すメソッドです。この例では Django の :ref:`Object-Relational マッパ <ref-models-querysets>` を使って ``NewsItem`` を返していますが、 :meth:`items()` は必ずしもモデルインスタ ンスを返さねばならないわけではありません。 Django モデルを使えばいくつか の機能を何もせずに使えるというだけの話で、 :meth:`items()` は望みのどんな 型のオブジェクトを返してもかまいません。 * RSS フィードの代わりに Atom フィードを生成する場合、 :attr:`description` 属性の代わりに :attr:`subtitle` 属性を設定してください。詳しくは :ref:`Atom フィードと RSS フィードを並行出力する <publishing-atom-and-rss-feeds-in-tandem>` を参照してください。 まだやるべきことが残っています。 RSS フィード中では、 ``<item>`` には ``<title>``, ``<link>``, ``<description>`` といったエレメントがあります。 そこで、これらのエレメントにどのデータを入れるのかをフレームワークに教える 必要があります。 * ``<title>`` や ``<description>`` の中身を指定するには、 :file:`feeds/latest_title.html` または :file:`feeds/latest_description.html` という名前の :ref:`Django テン プレート <topics-templates>` を作成します。 :attr:`latest` は URLconf 中に指定しておいた、フィードの :attr:`slug` です。 ``.html`` 拡張子 が必要なことに注意して下さい。 RSS システムはこれらのテンプレートを各 要素に対してレンダリングします。このとき、二つのテンプレートコンテキ スト変数を渡します: * ``{{ obj }}`` -- 現在のオブジェクト (:meth:`items()` の返すオブ ジェクトの中の一つ) です。 * ``{{ site }}`` -- 現在のサイトを表現する、 ``django.contrib.sites.models.Site`` オブジェクトです。この変数 は ``{{ site.domain }}`` や ``{{ site.name }}`` を参照する際に 便利です。最新の開発版の Django を使っていて、 sites フレームワー クを *使っていない* 場合、この値は ``django.contrib.sites.models.RequestSite`` オブジェクトになり ます。詳しくは :ref:`RequestSite の説明 <requestsite-objects>` を参照してください。 ``title`` や ``description`` のテンプレートを作成しなかった場合、 RSS フレームワークは ``"{{ obj }}"`` で表されるテンプレートをデフォルト値 として使います。すなわち、オブジェクトの文字列表現が使われます。 :class:`~django.contrib.syndication.feeds.Feed` クラスに ``title_template`` や ``description_template`` といった属性値を指定す れば、これらのテンプレートの名前を指定できます。 * ``<link>`` の内容を指定するには二つの方法があります。 :meth:`items()` の各要素毎に、Django はまずオブジェクトに対して ``get_absolute_url()`` メソッドを実行しようと試みます。このメソッドが なければ、 :class:`~django.contrib.syndication.feeds.Feed` クラスで定 義されている :meth:`item_link()` メソッドを呼び出そうとします。このと き、メソッドにはオブジェクト自体を引数 :attr:`item` として渡します。 ``get_absolute_url()`` や :meth:`item_link()` は、いずれも通常の Python 文字列で URL を返さねばなりません。また、 ``get_absolute_url()`` と同様、 :meth:`item_link()` の返す値は直接 URL に組み込めなければなりません。このため、プログラマは、必要に応じ て URL のクオート処理や変換を行って、全ての文字が ASCII 文字からなる 値に変換する責任があります。 * 上の LatestEntries の例では、以下のような簡単なフィードテンプレートに できます:: * latest_title.html: .. code-block:: html+django {{ obj.title }} * latest_description.html: .. code-block:: html+django {{ obj.description }} .. _chicagocrime.org: http://www.chicagocrime.org/ 複雑な例 --------- 配信フレームワークは、パラメタを使ったより複雑なフィードをサポートしています。 例えば、 `chicagocrime.org`_ では、シカゴ市内の全ての警官の巡回区域 (beat) ごとに最新の犯罪情報のフィードを提供しています。全ての巡回区域毎に :class:`~django.contrib.syndication.feeds.Feed` クラスを用意するのは馬鹿ら しい話です。 :ref:`DRY 則 <dry>` に反していますし、データの都合とプログラム ロジックを連結させてしまうことになります。その代わりに、配信フレームワーク では、フィードの URL に指定した情報に従って適切な要素を出力するような汎用の フィードを生成できるようにしています。 chicagocrime.org では、巡回区域単位のフィードに以下のような URL でアクセス できるようになっています: * :file:`/rss/beats/0613/` -- 0613 区の最近の犯罪を返します。 * :file:`/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 :file:`/rss/beats/0613/` でアクセスしたときの、 RSS フレー ムワークの基本的なアルゴリズムは以下の通りです: * フレームワークに URL :file:`/rss/beats/0613/` が渡されます。フレーム ワークは slug 以後の URL 部分を検出し、 slug 以後の文字列をスラッシュ (``"/"``) で分割して、 :class:`~django.contrib.syndication.feeds.Feed` クラスの :meth:`get_object()` メソッドの引数 ``bits`` に渡して呼び出します。上 の例では ``bits`` は ``['0613']`` になります。リクエストが :file:`/rss/beats/0613/foo/bar/` であれば ``bits`` は ``['0613', 'foo', 'bar']`` です。 * :meth:`get_object()` は指定された ``bits`` を使って適切な巡回区域を選 択する役割を担っています。上の場合では、 Django のデータベース API を 使って巡回区域を決定しています。 無効なパラメタが指定された場合、 :meth:`get_object()` は :exc:`django.core.exceptions.ObjectDoesNotExist` を返さねばなりません。 関数が失敗すると :exc:`Beat.DoesNotExist` を送出し、 :exc:`Beat.DoesNotExist` は :exc:`ObjectDoesNotExist` のサブクラスなので、 ``Beat.objects.get()`` 呼び出しの周りには ``try``/``except`` がありま せん。 :meth:`get_object()` の中で ``ObjectDoesNotExist`` を送出すると、 Django はリクエストに対して 404 エラーを返します。 .. versionadded:: 1.0 :meth:`get_object()` で :file:`/rss/beats/` を扱えるようになりまし た。 :meth:`get_object()` を使って :file:`/rss/beats/` を処理させる方法が あります。それは、 :data:`bits` が空のリストのときです。上の例では、 ``len(bits) !=1`` のとき、 :exc:`ObjectDoesNotExist` 例外を送出する ので、 :file:`/rss/beats/` は 404 エラーページを生成します。しかし、 実際にはここで好きな処理を行って構いません。たとえば、全ての beat の フィードを合わせたような結果を生成して返してもよいのです。 * フィードの ``<title>``, ``<link>``, および ``<description>`` を生成す るために、 Django はそれぞれ :meth:`title()`, :meth:`link()` および :meth:`description()` といったメソッドを使います。こうしたメソッドは 前述の例では単なる文字列でできたクラス属性でしたが、実際には文字列に もメソッドにもできます。 ``title``, ``link`` および ``description`` については、 Django は以下のようなアルゴリズムで値を決めます: * :meth:`get_object()` の返すオブジェクト ``obj`` を引数にして、メ ソッドを呼び出そうと試みます。 * 失敗した場合、メソッドを引数無しで呼び出そうと試みます。 * 失敗した場合、クラス属性を使います。 :meth:`link()` メソッドの中では、 ``obj`` が ``None`` の場合、すなわ ちURL が完全に指定されなかった場合の処理を定義しておかねばなりません。 この部分で、 ``obj`` が存在するかどうかチェックしない場合には、他のメ ソッドでも、 ``obj`` が ``None`` であるかチェックする必要があるでしょ う (:meth:`link()` メソッドは、フィード生成プロセスのきわめて初期段階 で呼び出されるので、例外ではじき出しておくのにいい場所です)。 * 最後に、上の例の :meth:`items()` には引数 ``obj`` があることに注意し て下さい。 :attr:`items` の内容を解決するアルゴリズムは上と同じです。 すなわち、まず :attr:`items(obj)`, 次いで :meth:`items()`, そしてクラ ス属性 :attr:`items`` (この値はリストでなければなりません) の順です。 下記の ``ExampleFeed`` クラスには、 :class:`~django.contrib.syndication.feeds.Feed` クラスの全てのメソッドと属 性についてのドキュメントが書かれています。 フィードの形式を指定する --------------------------- このフレームワークは、デフォルトでは RSS 2.0 のフィードを生成します。 生成するフィードの形式を変えたければ、 :class:`~django.contrib.syndication.feeds.Feed` クラスの ``feed_type`` 属性 を変更します:: from django.utils.feedgenerator import Atom1Feed class MyFeed(Feed): feed_type = Atom1Feed ``feed_type`` にはインスタンスではなくクラスオブジェクトを指定するよう注意 して下さい。 現在利用可能なフィードの型は以下の 3 つです: * :class:`django.utils.feedgenerator.Rss201rev2Feed` (RSS 2.01、デフォ ルトの形式。) * :class:`django.utils.feedgenerator.RssUserland091Feed` (RSS 0.91 形式。) * :class:`django.utils.feedgenerator.Atom1Feed` (Atom 1.0 形式。) エンクロージャ --------------- podcast のフィードを生成するときなどに使われるエンクロージャ (enclusure) の 指定には、 :attr:`item_enclosure_url`, :attr:`item_enclosure_length` および :attr:`item_enclosure_mime_type` フックを使って下さい。後述の使用例にある ``ExampleFeed`` クラスを参照してください。 言語 -------- 配信フレームワークによって生成されたフィードには、自動的に適切な ``<language>`` タグ (RSS 2.0) や ``xml:lang`` 属性 (Atom) が入ります。 これらの値には :setting:`LANGUAGE_CODE` を直接使います。 URL ---- :attr:`link` メソッド/属性は絶対 URL (すなわち ``"/blog/"``) またはドメイン やプロトコルを完全指定した URL (``"http://www.example.com/blog/"``) のいず れかを返さねばなりません。 :attr:`link` がドメインを返さない場合、配信フレー ムワークは現在のサイトのドメインを :setting:`SITE_ID <SITE_ID>` に従って挿 入します。 Atom フィードにはフィードの現在の場所を定義する ``<link rel="self">`` が必 要です。配信フレームワークは現在の SITE_ID の設定に従ってドメインから取り出 した値を自動的に入れるようになっています。 .. _publishing-atom-and-rss-feeds-in-tandem: Atom フィードと RSS フィードを並行出力する --------------------------------------------- Atom と RSS の *両方の* バージョンを利用したい開発者もいることでしょう。 Django を使えば簡単に実現できます。自作の :class:`~django.contrib.syndication.feeds.Feed` クラスをサブクラス化して、 :attr:`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 フィードは :attr:`description` を使っています。一方、 Atom フィードでは :attr:`subtitle` を使っています。Atom フィードはフィー ドレベルの :attr:`description` を持たず、 :attr:`subtitle` を持っている からです。 :class:`~django.contrib.syndication.feeds.Feed` クラスに :attr:`description` を定義しておいても、Django は :attr:`description` の値を自動的に :attr:`subtitle` エレメントに入れたりはしません。 :attr:`subtitle` と :attr:`description` は必ずしも同じものを指さないか らです。その代わり、適切な説明の入った文字列をモデルの :attr:`subtitle` 属性として指定せねばなりません。 上の例では、たまたま RSS フィードの :attr:`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 クラスリファレンス ----------------------- .. class:: django.contrib.syndication.feeds.Feed この節の例では、 :class:`~django.contrib.syndication.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`` クラス --------------------------- :mod:`~django.utils.feedgenerator` モジュールには、ベースクラス: .. class:: django.utils.feedgenerator.SyndicationFeed と、以下のサブクラスが定義されています: .. class:: django.utils.feedgenerator.RssUserland091Feed .. class:: django.utils.feedgenerator.Rss201rev2Feed .. class:: django.utils.feedgenerator.Atom1Feed これらのクラスはいずれも、特定のタイプの XML を生成する方法を知っており、 以下のような共通のインタフェースを持っています: .. method:: SyndicationFeed.__init__(**kwargs) メタデータの入った辞書をもとにフィードを生成します。メタデータはフィー ド全体に適用されます。以下の引数が必須です: * ``title`` * ``link`` * ``description`` また、以下のようなオプションキーワードをサポートしています: * ``language`` * ``author_email`` * ``author_name`` * ``author_link`` * ``subtitle`` * ``categories`` * ``feed_url`` * ``feed_copyright`` * ``feed_guid`` * ``ttl`` これ以外のキーワード引数を ``__init__`` に渡すと、 ``self.feed`` に保存 されます。使い方は `カスタムのフィードジェネレータ <#ref-contrib-syndication-custom-feed-generator>`_ を参照してください。 パラメタは全て Unicode オブジェクトで指定します。ただし、 ``categories`` は Unicode オブジェクトのリストです。 .. method:: SyndicationFeed.add_item(**kwargs) 指定のパラメタをもった項目をフィードに追加します。 以下の引数は必須です: * ``title`` * ``link`` * ``description`` また、以下のオプションの引数があります: * ``author_email`` * ``author_name`` * ``author_link`` * ``pubdate`` * ``comments`` * ``unique_id`` * ``enclosure`` * ``categories`` * ``item_copyright`` * ``ttl`` それ以外のキーワード引数は `カスタムのフィードジェネレータ <#ref-contrib-syndication-custom-feed-generator>`_ 用に保存されます。 パラメタには Unicode オブジェクトを指定します。ただし: * ``pubdate`` は `Python datetime 型オブジェクト`_ にします。 * ``enclosure`` は ``feedgenerator.Enclosure`` のインスタンスにします。 * ``categories`` は Unicode オブジェクトのシークエンスにします。 .. method:: SyndicationFeed.write(outfile, encoding) フィードを指定のエンコーディングでファイルライクオブジェクト outfile に 出力します。 .. method:: SyndicationFeed.writeString(encoding) フィードを指定のエンコーディングの文字列として返します。 以下の例では 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> .. _django/utils/feedgenerator.py: http://code.djangoproject.com/browser/django/trunk/django/utils/feedgenerator.py .. _Python datetime object: http://www.python.org/doc/current/lib/module-datetime.html .. _`Python datetime 型オブジェクト`: `Python datetime object`_ .. _ref-contrib-syndication-custom-feed-generator: カスタムのフィードジェネレータ --------------------------------- カスタムのフォーマットでフィードを生成したいなら、二つ方法があります。 完全に独自の形式のフィードなら、 ``SyndicationFeed`` をサブクラス化して、 ``write()`` および ``writeString()`` メソッドを完全に書き直すとよいでしょう。 しかし、 (GeoRSS_ や Apple の `iTunes podcast フォーマット <http://www.apple.com/itunes/store/podcaststechspecs.html>`_ )のように、既 存のフィードフォーマットから派生したものであれば、もっといい選択肢がありま す。この手の派生フォーマットは、元のフォーマットにエレメントや属性を追加し ていて、 ``SyndicationFeed`` のメソッドには、こうした追加の属性を取得するた めのものがあります。ですから、適切なフィードクラス (``Atom1Feed`` や ``Rss201rev2Feed``) をサブクラス化して、コールバックを拡張すればよいのです。 拡張用のメソッドを以下に示します: .. _georss: http://georss.org/ ``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') もちろん、カスタムのフィードクラスを定義するには他にもたくさん作業が必要で すが、上の例を見れば基本的な考え方は理解できるはずです。 .. _XMLGenerator: http://docs.python.org/dev/library/xml.sax.utils.html#xml.sax.saxutils.XMLGenerator