# Django 6.0.7 ドキュメント

# 配信 (syndication) フィード フレームワーク

Django には、RSS と Atom フィードを作成するための高レベルな配信 (syndication) フィード生成フレームワークが付属しています。

任意の配信フィードを作成するには、短い Python クラスを書くだけで済みます。好きなだけフィードを作成できます。

Djangoには、低レベルのフィード生成APIも付属しています。ウェブコンテキストの外や、他の低レベルな方法でフィードを生成したい場合に使用してください。

## 高レベルのフレームワーク

### 概要

高レベルのフィード生成フレームワークは `Feed` クラスによって提供されます。フィードを作成するには、 `Feed` クラスを記述し、 URLconf でそのインスタンスを指定します。

### `Feed` クラス

`Feed` クラスは配信フィードを表す Python クラスです。フィードは単純なもの (例えば、"サイトニュース" フィードや、ブログの最新エントリを表示する基本的なフィード) もあれば、より複雑なもの (例えば、特定のカテゴリに属する全てのブログエントリを表示するフィード (カテゴリは可変)) もあります。

フィードクラスは `django.contrib.syndication.views.Feed` のサブクラスです。これらはコードベースのどこにでも置くことができます。

`Feed` クラスのインスタンスは、 URLconf で使用できるビューです。

### 簡単な例

この単純な例は、ある警察のニュースサイトから引用したもので、最新の5つのニュースのフィードを記述しています:

    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])

このフィードにURLを接続するには、 URLconf にFeedオブジェクトのインスタンスを配置します。例えば:

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

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

備考:

- Feedクラスは `django.contrib.syndication.views.Feed` のサブクラスです。

- `title`、`link`、および `description` は、それぞれ標準RSSの `<title>`, `<link>`, `<description>` 要素に対応します。

- `items()` は、フィードに含めるべきオブジェクトのリストを返すメソッドです。この例では、Djangoの ORM を使用して `NewsItem` オブジェクトを返しますが、 `items()` は必ずモデルインスタンスを返す必要はありません。Django モデルを使用することで、いくつかの機能が「タダ」で提供されますが、 `items()` は任意の種類のオブジェクトを返すことができます。

- Atom フィードを作成する場合、RSS フィードではなく、`description` 属性の代わりに `subtitle` 属性を設定してください。例については、後述の Publishing Atom and RSS feeds in tandem を参照してください。

まだやるべきことが一つあります。RSSフィードでは、各 `<item>` には `<title>`, `<link>`, そして `<description>` が含まれています。これらの要素にどんなデータを入れるべきか、フレームワークに伝える必要があります。

- `<title>` と `<description>` の内容について、Djangoは `Feed` クラスでメソッド `item_title()` と `item_description()` を呼び出そうとします。これらには、オブジェクト自体を表す単一のパラメータ `item` が渡されます。これらはオプションであり、デフォルトではオブジェクトの文字列表現が両方に使用されます。

  タイトルや説明文に特別な書式を設定したい場合は、 Django テンプレート を代わりに使用できます。そのパスは `Feed` クラスの `title_template` と `description_template` 属性で指定できます。テンプレートはアイテムごとにレンダリングされ、2つのテンプレートコンテキスト変数に渡されます:

  - `{{ obj }}` -- 現在のオブジェクト (`items()` で返したオブジェクトのいずれか)。

  - `{{ site }}` ―― 現在のサイトを表す `django.contrib.sites.models.Site` オブジェクト。これは `{{ site.domain }}` や `{{ site.name }}` に便利です。Django サイトフレームワークがインストールされていない場合は、これは `RequestSite` オブジェクトに設定されます。詳細は、サイトフレームワークのドキュメントの RequestSite のセクション を参照してください。

  記述テンプレートを使用した以下の a complex example を参照してください。

  Feed.get_context_data(**kwargs)

    必要な変数が2つ以上ある場合、タイトルと説明テンプレートに追加情報を渡す方法もあります。その場合は、`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().get_context_data(**kwargs)
                context["foo"] = "bar"
                return context

  テンプレートは以下の通りです:

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

  このメソッドは、`items()` で返されたリストの各アイテムごとに、次のキーワード引数とともに一度ずつ呼び出されます:

  - `item`: 現在のアイテム。後方互換性のため、このコンテキスト変数の名前は `{{ obj }}` です。

  - `obj`: `get_object()` で返されるオブジェクト。デフォルトでは、テンプレートでの混乱を避けるため `{{ obj }}` (前述) で公開されませんが、 `get_context_data()` の実装で使用できます。

  - `site`: 上記で説明した現在のサイト。

  - `request`: 現在のリクエスト。

  `get_context_data()` の動作は ジェネリックビュー と同様です。親クラスからコンテキストデータを取得するために `super()` を呼び出し、自分のデータを追加して、修正された辞書を返すことになっています。

- To specify the contents of `<link>`, you have two options. For each item in `items()`, Django first tries calling the `item_link()` method on the `Feed` class. In a similar way to the title and description, it is passed a single parameter, `item`. If that method doesn't exist, Django tries executing a `get_absolute_url()` method on that object. Both `get_absolute_url()` and `item_link()` should return the item's URL as a normal Python string. As with `get_absolute_url()`, the result of `item_link()` will be included directly in the URL, so you are responsible for doing all necessary URL quoting and conversion to ASCII inside the method itself.

### 複雑な例

このフレームワークは、引数を通じて、より複雑なフィードもサポートしています。

たとえば、あるウェブサイトが、都市内の各警察管轄地域の最近の犯罪についてのRSSフィードを提供しているとします。各警察の管轄地域ごとに `Feed` クラスを別々に作成するのは愚かなことです。それは DRY原則 に反し、データをプログラミングロジックに結びつけてしまいます。代わりに、配信 (syndication) フレームワークを使用すると、URLconf から渡された引数にアクセスできます。そのため、フィードのURL内の情報に基づいてアイテムを出力できます。

警察の管轄地域のフィードは次のようなURLを介してアクセスできます:

- `/beats/613/rss/` ―― 613番担当地域の最近の犯罪情報を返します。

- "/beats/1424/rss/" ―― 1424番担当地域の最近の犯罪を返します。

これらは、次のような URLconf 行とマッチするでしょう:

    path("beats/<int:beat_id>/rss/", BeatFeed()),

ビューと同様に、URLの引数はリクエストオブジェクトと共に `get_object()` メソッドに渡されます。

これらの管轄地域に特化したフィードのコードは以下の通りです:

    from django.contrib.syndication.views import Feed

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

        def get_object(self, request, beat_id):
            return Beat.objects.get(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]

フィードの `<title>`, `<link>`, `<description>` を生成するために、 Django は `title()`, `link()`, `description()` メソッドを使います。前の例では、これらは文字列のクラス属性でしたが、この例では、文字列 または メソッドを指定できます。 `title`、`link`、`description` のそれぞれについて、 Django は以下のアルゴリズムに従います

- まず、 `obj` を引数にして、メソッドを呼び出そうとします。ここで、 `obj` は `get_object()` によって返されたオブジェクトです

- それが失敗した場合、引数なしでメソッドを呼び出そうとします。

- それができない場合は、クラス属性を使用します。

また、`items()` も同じアルゴリズムに従います。最初に `items(obj)` を試し、次に `items()`、最後に `items` クラス属性（リストであるべきです）を試します。

アイテムの説明用にテンプレートを使用しています。これは最小限の例です:

    {{ obj.description }}

ただし、フォーマットは必要に応じて追加できます。

以下の `ExampleFeed` クラスは、 `Feed` クラスのメソッドと属性に関する完全なドキュメントを提供します。

### フィードの種類を指定する

デフォルトでは、このフレームワークで作成されたフィードはRSS 2.0を使用します。

これを変更するには、次のように `Feed` クラスに `feed_type` 属性を追加します:

    from django.utils.feedgenerator import Atom1Feed

    class MyFeed(Feed):
        feed_type = Atom1Feed

`feed_type` にはインスタンスではなく、クラスオブジェクトを設定することに注意してください。

現在利用可能なフィードタイプは以下の通りです:

- `django.utils.feedgenerator.Rss201rev2Feed` (RSS 2.01。デフォルト。)

- `django.utils.feedgenerator.RssUserland091Feed` (RSS 0.91.)

- `django.utils.feedgenerator.Atom1Feed` (Atom 1.0.)

### エンクロージャ (Enclosure)

ポッドキャストフィードを作成する際に使用されるエンクロージャ (enclosure) を指定するには、`item_enclosures` フックを使用するか、またはアイテムごとに1つのエンクロージャのみを持つ場合は代わりに `item_enclosure_url`、`item_enclosure_length`、`item_enclosure_mime_type` フックを使用します。使用例については、以下の `ExampleFeed` クラスを参照してください。

### 言語

Feeds created by the syndication framework automatically include the appropriate `<language>` tag (RSS 2.0) or `xml:lang` attribute (Atom). By default, this is `django.utils.translation.get_language()`. You can change it by setting the `language` class attribute.

### URL

`link` メソッド/属性は絶対パス (例: `"/blog/"`) または完全修飾ドメインとプロトコルを含むURL (例：`"https://www.example.com/blog/"`) を返すことができます。もし `link` がドメインを返さない場合、配信フレームワークは `SITE_ID 設定` に従って、現在のサイトのドメインを挿入します。

Atom フィードには、フィードの現在の場所を定義する `<link rel="self">` が必要です。配信フレームワークは、`SITE_ID` 設定に従って、現在のサイトのドメインを使用して、これを自動的に設定します。

### Atom と RSS フィードを同時に公開する

フィードの Atom 版と RSS 版の 両方 を利用したい開発者もいるでしょう。そのためには、 `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フィードは `description` を使っていますが、Atomフィードは `subtitle` を使っています。Atomフィードはフィードレベルの "description" を提供しませんが、"subtitle" を提供 する からです。

`Feed` クラスに `description` を提供した場合、サブタイトルと説明が必ずしも同じものではないため、Django は自動的にそれを `subtitle` 要素に入れ ません 。代わりに、 `subtitle` 属性を定義するべきです。

上記の例では、Atomフィードの `subtitle` をRSSフィードの `description` に設定していますが、これは既にかなり短いためです。

そして、それに伴うURLconfは次のとおりです:

    from django.urls import path
    from myproject.feeds import AtomSiteNewsFeed, RssSiteNewsFeed

    urlpatterns = [
        # ...
        path("sitenews/rss/", RssSiteNewsFeed()),
        path("sitenews/atom/", AtomSiteNewsFeed()),
        # ...
    ]

### `Feed` クラスのリファレンス

class views.Feed

この例は、 `Feed` クラスの可能な全ての属性とメソッドを示しています:

    from django.contrib.syndication.views import Feed
    from django.utils import feedgenerator

    class ExampleFeed(Feed):
        # FEED TYPE -- Optional. This should be a class that subclasses
        # django.utils.feedgenerator.SyndicationFeed. This designates
        # which type of feed this should be: RSS 2.0, Atom 1.0, etc. If
        # you don't specify feed_type, your feed will be RSS 2.0. This
        # should be a class, not an instance of the class.

        feed_type = feedgenerator.Rss201rev2Feed

        # TEMPLATE NAMES -- Optional. These should be strings
        # representing names of Django templates that the system should
        # use in rendering the title and description of your feed items.
        # Both are optional. If a template is not specified, the
        # item_title() or item_description() methods are used instead.

        title_template = None
        description_template = None

        # LANGUAGE -- Optional. This should be a string specifying a language
        # code. Defaults to django.utils.translation.get_language().
        language = "de"

        # TITLE -- One of the following three is required. The framework
        # looks for them in this order.

        def title(self, obj):
            """
            Takes the object returned by get_object() and returns the
            feed's title as a normal Python string.
            """

        def title(self):
            """
            Returns the feed's title as a normal Python string.
            """

        title = "foo"  # Hard-coded title.

        # LINK -- One of the following three is required. The framework
        # looks for them in this order.

        def link(self, obj):
            """
            # Takes the object returned by get_object() and returns the URL
            # of the HTML version of the feed as a normal Python string.
            """

        def link(self):
            """
            Returns the URL of the HTML version of the feed as a normal Python
            string.
            """

        link = "/blog/"  # Hard-coded URL.

        # FEED_URL -- One of the following three is optional. The framework
        # looks for them in this order.

        def feed_url(self, obj):
            """
            # Takes the object returned by get_object() and returns the feed's
            # own URL as a normal Python string.
            """

        def feed_url(self):
            """
            Returns the feed's own URL as a normal Python string.
            """

        feed_url = "/blog/rss/"  # Hard-coded URL.

        # GUID -- One of the following three is optional. The framework looks
        # for them in this order. This property is only used for Atom feeds
        # (where it is the feed-level ID element). If not provided, the feed
        # link is used as the ID.

        def feed_guid(self, obj):
            """
            Takes the object returned by get_object() and returns the globally
            unique ID for the feed as a normal Python string.
            """

        def feed_guid(self):
            """
            Returns the feed's globally unique ID as a normal Python string.
            """

        feed_guid = "/foo/bar/1234"  # Hard-coded guid.

        # DESCRIPTION -- One of the following three is required. The framework
        # looks for them in this order.

        def description(self, obj):
            """
            Takes the object returned by get_object() and returns the feed's
            description as a normal Python string.
            """

        def description(self):
            """
            Returns the feed's description as a normal Python string.
            """

        description = "Foo bar baz."  # Hard-coded description.

        # AUTHOR NAME --One of the following three is optional. The framework
        # looks for them in this order.

        def author_name(self, obj):
            """
            Takes the object returned by get_object() and returns the feed's
            author's name as a normal Python string.
            """

        def author_name(self):
            """
            Returns the feed's author's name as a normal Python string.
            """

        author_name = "Sally Smith"  # Hard-coded author name.

        # AUTHOR EMAIL --One of the following three is optional. The framework
        # looks for them in this order.

        def author_email(self, obj):
            """
            Takes the object returned by get_object() and returns the feed's
            author's email as a normal Python string.
            """

        def author_email(self):
            """
            Returns the feed's author's email as a normal Python string.
            """

        author_email = "test@example.com"  # Hard-coded author email.

        # AUTHOR LINK --One of the following three is optional. The framework
        # looks for them in this order. In each case, the URL should include
        # the scheme (such as "https://") and domain name.

        def author_link(self, obj):
            """
            Takes the object returned by get_object() and returns the feed's
            author's URL as a normal Python string.
            """

        def author_link(self):
            """
            Returns the feed's author's URL as a normal Python string.
            """

        author_link = "https://www.example.com/"  # Hard-coded author URL.

        # CATEGORIES -- One of the following three is optional. The framework
        # looks for them in this order. In each case, the method/attribute
        # should return an iterable object that returns strings.

        def categories(self, obj):
            """
            Takes the object returned by get_object() and returns the feed's
            categories as iterable over strings.
            """

        def categories(self):
            """
            Returns the feed's categories as iterable over strings.
            """

        categories = ["python", "django"]  # Hard-coded list of categories.

        # COPYRIGHT NOTICE -- One of the following three is optional. The
        # framework looks for them in this order.

        def feed_copyright(self, obj):
            """
            Takes the object returned by get_object() and returns the feed's
            copyright notice as a normal Python string.
            """

        def feed_copyright(self):
            """
            Returns the feed's copyright notice as a normal Python string.
            """

        feed_copyright = "Copyright (c) 2007, Sally Smith"  # Hard-coded copyright notice.

        # TTL -- One of the following three is optional. The framework looks
        # for them in this order. Ignored for Atom feeds.

        def ttl(self, obj):
            """
            Takes the object returned by get_object() and returns the feed's
            TTL (Time To Live) as a normal Python string.
            """

        def ttl(self):
            """
            Returns the feed's TTL as a normal Python string.
            """

        ttl = 600  # Hard-coded Time To Live.

        # STYLESHEETS -- Optional. To set, provide one of the following three.
        # The framework looks for them in this order.

        def stylesheets(self, obj):
            """
            Takes the object returned by get_object() and returns the feed's
            stylesheets (as URL strings or as Stylesheet instances).
            """

        def stylesheets(self):
            """
            Returns the feed's stylesheets (as URL strings or Stylesheet
            instances).
            """

        # Hardcoded stylesheets.
        stylesheets = ["/stylesheet1.xsl", "stylesheet2.xsl"]

        # ITEMS -- One of the following three is required. The framework looks
        # for them in this order.

        def items(self, obj):
            """
            Takes the object returned by get_object() and returns a list of
            items to publish in this feed.
            """

        def items(self):
            """
            Returns a list of items to publish in this feed.
            """

        items = ["Item 1", "Item 2"]  # Hard-coded items.

        # GET_OBJECT -- This is required for feeds that publish different data
        # for different URL parameters. (See "A complex example" above.)

        def get_object(self, request, *args, **kwargs):
            """
            Takes the current request and the arguments from the URL, and
            returns an object represented by this feed. Raises
            django.core.exceptions.ObjectDoesNotExist on error.
            """

        # ITEM TITLE AND DESCRIPTION -- If title_template or
        # description_template are not defined, these are used instead. Both are
        # optional, by default they will use the string representation of the
        # item.

        def item_title(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            title as a normal Python string.
            """

        def item_title(self):
            """
            Returns the title for every item in the feed.
            """

        item_title = "Breaking News: Nothing Happening"  # Hard-coded title.

        def item_description(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            description as a normal Python string.
            """

        def item_description(self):
            """
            Returns the description for every item in the feed.
            """

        item_description = "A description of the item."  # Hard-coded description.

        def get_context_data(self, **kwargs):
            """
            Returns a dictionary to use as extra context if either
            description_template or item_template are used.

            Default implementation preserves the old behavior
            of using {'obj': item, 'site': current_site} as the context.
            """

        # ITEM LINK -- One of these three is required. The framework looks for
        # them in this order.

        # First, the framework tries the two methods below, in
        # order. Failing that, it falls back to the get_absolute_url()
        # method on each item returned by items().

        def item_link(self, item):
            """
            Takes an item, as returned by items(), and returns the item's URL.
            """

        def item_link(self):
            """
            Returns the URL for every item in the feed.
            """

        # ITEM_GUID -- The following method is optional. If not provided, the
        # item's link is used by default.

        def item_guid(self, obj):
            """
            Takes an item, as return by items(), and returns the item's ID.
            """

        # ITEM_GUID_IS_PERMALINK -- The following method is optional. If
        # provided, it sets the 'isPermaLink' attribute of an item's
        # GUID element. This method is used only when 'item_guid' is
        # specified.

        def item_guid_is_permalink(self, obj):
            """
            Takes an item, as returned by items(), and returns a boolean.
            """

        item_guid_is_permalink = False  # Hardcoded value

        # ITEM AUTHOR NAME -- One of the following three is optional. The
        # framework looks for them in this order.

        def item_author_name(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            author's name as a normal Python string.
            """

        def item_author_name(self):
            """
            Returns the author name for every item in the feed.
            """

        item_author_name = "Sally Smith"  # Hard-coded author name.

        # ITEM AUTHOR EMAIL --One of the following three is optional. The
        # framework looks for them in this order.
        #
        # If you specify this, you must specify item_author_name.

        def item_author_email(self, obj):
            """
            Takes an item, as returned by items(), and returns the item's
            author's email as a normal Python string.
            """

        def item_author_email(self):
            """
            Returns the author email for every item in the feed.
            """

        item_author_email = "test@example.com"  # Hard-coded author email.

        # ITEM AUTHOR LINK -- One of the following three is optional. The
        # framework looks for them in this order. In each case, the URL should
        # include the scheme (such as "https://") and domain name.
        #
        # If you specify this, you must specify item_author_name.

        def item_author_link(self, obj):
            """
            Takes an item, as returned by items(), and returns the item's
            author's URL as a normal Python string.
            """

        def item_author_link(self):
            """
            Returns the author URL for every item in the feed.
            """

        item_author_link = "https://www.example.com/"  # Hard-coded author URL.

        # ITEM ENCLOSURES -- One of the following three is optional. The
        # framework looks for them in this order. If one of them is defined,
        # ``item_enclosure_url``, ``item_enclosure_length``, and
        # ``item_enclosure_mime_type`` will have no effect.

        def item_enclosures(self, item):
            """
            Takes an item, as returned by items(), and returns a list of
            ``django.utils.feedgenerator.Enclosure`` objects.
            """

        def item_enclosures(self):
            """
            Returns the ``django.utils.feedgenerator.Enclosure`` list for every
            item in the feed.
            """

        item_enclosures = []  # Hard-coded enclosure list

        # ITEM ENCLOSURE URL -- One of these three is required if you're
        # publishing enclosures and you're not using ``item_enclosures``. The
        # framework looks for them in this order.

        def item_enclosure_url(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            enclosure URL.
            """

        def item_enclosure_url(self):
            """
            Returns the enclosure URL for every item in the feed.
            """

        item_enclosure_url = "/foo/bar.mp3"  # Hard-coded enclosure link.

        # ITEM ENCLOSURE LENGTH -- One of these three is required if you're
        # publishing enclosures and you're not using ``item_enclosures``. The
        # framework looks for them in this order. In each case, the returned
        # value should be either an integer, or a string representation of the
        # integer, in bytes.

        def item_enclosure_length(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            enclosure length.
            """

        def item_enclosure_length(self):
            """
            Returns the enclosure length for every item in the feed.
            """

        item_enclosure_length = 32000  # Hard-coded enclosure length.

        # ITEM ENCLOSURE MIME TYPE -- One of these three is required if you're
        # publishing enclosures and you're not using ``item_enclosures``. The
        # framework looks for them in this order.

        def item_enclosure_mime_type(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            enclosure MIME type.
            """

        def item_enclosure_mime_type(self):
            """
            Returns the enclosure MIME type for every item in the feed.
            """

        item_enclosure_mime_type = "audio/mpeg"  # Hard-coded enclosure MIME type.

        # ITEM PUBDATE -- It's optional to use one of these three. This is a
        # hook that specifies how to get the pubdate for a given item.
        # In each case, the method/attribute should return a Python
        # datetime.datetime object.

        def item_pubdate(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            pubdate.
            """

        def item_pubdate(self):
            """
            Returns the pubdate for every item in the feed.
            """

        item_pubdate = datetime.datetime(2005, 5, 3)  # Hard-coded pubdate.

        # ITEM UPDATED -- It's optional to use one of these three. This is a
        # hook that specifies how to get the updateddate for a given item.
        # In each case, the method/attribute should return a Python
        # datetime.datetime object.

        def item_updateddate(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            updateddate.
            """

        def item_updateddate(self):
            """
            Returns the updateddate for every item in the feed.
            """

        item_updateddate = datetime.datetime(2005, 5, 3)  # Hard-coded updateddate.

        # ITEM CATEGORIES -- It's optional to use one of these three. This is
        # a hook that specifies how to get the list of categories for a given
        # item. In each case, the method/attribute should return an iterable
        # object that returns strings.

        def item_categories(self, item):
            """
            Takes an item, as returned by items(), and returns the item's
            categories.
            """

        def item_categories(self):
            """
            Returns the categories for every item in the feed.
            """

        item_categories = ["python", "django"]  # Hard-coded categories.

        # ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the
        # following three is optional. The framework looks for them in this
        # order.

        def item_copyright(self, obj):
            """
            Takes an item, as returned by items(), and returns the item's
            copyright notice as a normal Python string.
            """

        def item_copyright(self):
            """
            Returns the copyright notice for every item in the feed.
            """

        item_copyright = "Copyright (c) 2007, Sally Smith"  # Hard-coded copyright notice.

        # ITEM COMMENTS URL -- It's optional to use one of these three. This is
        # a hook that specifies how to get the URL of a page for comments for a
        # given item.

        def item_comments(self, obj):
            """
            Takes an item, as returned by items(), and returns the item's
            comments URL as a normal Python string.
            """

        def item_comments(self):
            """
            Returns the comments URL for every item in the feed.
            """

        item_comments = "https://www.example.com/comments"  # Hard-coded comments URL

## 低レベルのフレームワーク

舞台裏では、高水準のRSSフレームワークがフィードのXMLを生成するために、より低水準のフレームワークを使用しています。このフレームワークは単一のモジュールに存在します: django/utils/feedgenerator.py 。

このフレームワークを使用して、低レベルのフィードを生成します。独自のフィードジェネレータサブクラスを作成して `feed_type` `Feed` オプションで使用することもできます。

### `SyndicationFeed` クラス

`feedgenerator` モジュールには以下の基底クラスが含まれています:

- `django.utils.feedgenerator.SyndicationFeed`

サブクラスは以下です:

- `django.utils.feedgenerator.RssUserland091Feed`

- `django.utils.feedgenerator.Rss201rev2Feed`

- `django.utils.feedgenerator.Atom1Feed`

これら3つのクラスは、特定の種類のフィードをXMLとしてレンダリングする方法を知っています。これらはこのインターフェイスを共有しています:

`SyndicationFeed.__init__()`

  与えられたメタデータの辞書でフィードを初期化します。これはフィード全体に適用されます。必須のキーワード引数は以下の通りです:

  - `title`

  - `link`

  - `description`

  他にもいくつかのオプションキーワードがあります:

  - `language`

  - `author_email`

  - `author_name`

  - `author_link`

  - `subtitle`

  - `categories`

  - `feed_url`

  - `feed_copyright`

  - `feed_guid`

  - `ttl`

  - `stylesheets`

  `__init__` に渡された追加のキーワード引数は、 custom feed generators での使用のために `self.feed` に格納されます。

  以下の2つを除き、パラメータは文字列を指定してください。

  - `categories` は文字列のシーケンスであるべきです。

  - `stylesheets` は、文字列または `Stylesheet` インスタンスのいずれかのシーケンスを指定する必要があります。

  XMLドキュメントでは、いくつかの制御文字が 許可されていない ことに注意してください。コンテンツにそれらが含まれている場合、フィードを生成する際に `ValueError` に遭遇するかもしれません。

`SyndicationFeed.add_item()`

  指定されたパラメータを使用してフィードにアイテムを追加します。

  必須キーワード引数は以下の通りです:

  - `title`

  - `link`

  - `description`

  オプションのキーワード引数は次のとおりです:

  - `author_email`

  - `author_name`

  - `author_link`

  - `pubdate`

  - `comments`

  - `unique_id`

  - `enclosures`

  - `categories`

  - `item_copyright`

  - `ttl`

  - `updateddate`

  追加のキーワード引数は custom feed generators 用に保存されます。

  パラメータを指定する場合は、文字列でなければなりません:

  - `pubdate` は Python の `datetime` オブジェクトであるべきです。

  - `updateddate` はPythonの `datetime` オブジェクトでなければなりません。

  - `enclosures` は `django.utils.feedgenerator.Enclosure` インスタンスのリストであるべきです。

  - `categories` は文字列のシーケンスであるべきです。

`SyndicationFeed.write()`

  指定されたエンコーディングでフィードを outfile に出力します。outfile はファイルライクなオブジェクトです。

`SyndicationFeed.writeString()`

  指定されたエンコーディングでフィードを文字列として返します。

例えば、Atom 1.0 フィードを作成して標準出力に出力するには、次のようにします:

    >>> from django.utils import feedgenerator
    >>> from datetime import datetime
    >>> f = feedgenerator.Atom1Feed(
    ...     title="My Blog",
    ...     link="https://www.example.com/",
    ...     description="In which I write about what I ate today.",
    ...     language="en",
    ...     author_name="Myself",
    ...     feed_url="https://example.com/atom.xml",
    ... )
    >>> f.add_item(
    ...     title="Hot dog today",
    ...     link="https://www.example.com/entries/1/",
    ...     pubdate=datetime.now(),
    ...     description="<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</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>

### カスタムフィードジェネレータ

カスタムフィード形式を作成する必要がある場合、いくつかのオプションがあります。

フィードフォーマットが完全にカスタムである場合は、`SyndicationFeed` をサブクラス化し、`write()` メソッドと `writeString()` メソッドを完全に置き換える必要があります。

しかし、フィードフォーマットがRSSやAtom（例えば、 GeoRSS 、Appleの iTunes podcast format など）の派生形式である場合、より良い選択肢があります。これらのタイプのフィードは、通常、基本となるフォーマットに追加の要素や属性を追加し、 `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.add_item()` に渡されるすべてのデータの辞書です。

`SyndicationFeed.add_item_elements(self, handler, item)`

  各アイテム (`item`/`entry`) 要素に要素を追加するためのコールバックです。 `handler` と `item` は上記の通りです。

警告

これらのメソッドをオーバーライドする場合は、基底クラスのメソッドを必ず呼び出してください。これらは、それぞれのフィードフォーマットに必要な要素を追加するためです。

たとえば、iTunesのRSSフィードジェネレーターの実装を次のように始めることができます:

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

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

完全なカスタムフィードクラスを作成するには、まだ多くの作業が必要ですが、上記の例で基本的な考え方を示すことができるはずです。

### フィードのスタイルシート

RSS フィードをブラウザで見やすく表示させたい場合は、XML ファイルに対してスタイル情報を指定する必要があります。通常、XSLT や CSS 形式で指定します。

スタイル情報を RSS フィードに追加するには、フィードクラスの stylesheets 属性を設定します。

URLをハードコードした場合。

    from django.contrib.syndication.views import Feed

    class FeedWithHardcodedStylesheet(Feed):
        stylesheets = [
            "https://example.com/rss_stylesheet.xslt",
        ]

Django の静的ファイルシステムを使うこともできます。

    from django.contrib.syndication.views import Feed
    from django.templatetags.static import static

    class FeedWithStaticFileStylesheet(Feed):
        stylesheets = [
            static("rss_styles.xslt"),
        ]

別の方法として、プロジェクト内に XSLT ドキュメントをレンダリングするビューを用意することもできます。その場合、以下のようにリンクを指定できます。

    from django.contrib.syndication.views import Feed
    from django.urls import reverse_lazy

    class FeedWithStylesheetView(Feed):
        stylesheets = [
            reverse_lazy("your-custom-view-name"),
        ]

通常、与えられたURLの拡張子から MIME タイプが推測されますが、うまくいかない場合は `Stylesheet` クラスを使用して指定することもできます。

    from django.contrib.syndication.views import Feed
    from django.utils.feedgenerator import Stylesheet

    class FeedWithHardcodedStylesheet(Feed):
        stylesheets = [
            Stylesheet("https://example.com/rss_stylesheet", mimetype="text/xsl"),
        ]

同様に、 `screen` (Djangoのデフォルト)ではなく `media` 属性を使用したい場合も、 `Stylesheet` クラスを使用することができます。

    from django.contrib.syndication.views import Feed
    from django.utils.feedgenerator import Stylesheet

    class FeedWithHardcodedStylesheet(Feed):
        stylesheets = [
            Stylesheet("https://example.com/rss_stylesheet.xslt", media="print"),
        ]

これらのオプションは複数のスタイルシートを使用する際に並列させることができます。

    from django.contrib.syndication.views import Feed
    from django.utils.feedgenerator import Stylesheet

    class MultiStylesheetFeed(Feed):
        stylesheets = [
            "/stylesheet1.xsl",
            Stylesheet("/stylesheet2.xsl"),
        ]