サイトマップ・フレームワーク

Djangoには、 sitemap XML ファイルを作成するための高レベルなサイトマップ生成フレームワークが付属しています。

概要

サイトマップとは、検索エンジンのインデクサーに、ページの変更頻度や、あるページがサイト内の他のページと比較してどの程度「重要」であるかを伝える、ウェブサイト上のXMLファイルのことです。この情報は、検索エンジンがあなたのサイトをインデックスするのに役立ちます。

Django サイトマップフレームワークは、この情報を Python コードで表現することで、XML ファイルの作成を自動化します。

これは Django の 配信 (syndication) フレームワーク のように動作します。サイトマップを作成するには、 Sitemap クラスを書き、 URLconf の中でそれを指定します。

インストール

サイトマップ アプリをインストールするには、以下の手順に従ってください。

  1. 'django.contrib.sitemaps'INSTALLED_APPS 設定に追加します。
  2. TEMPLATES 設定には、DjangoTemplates バックエンドが含まれており、APP_DIRS オプションが True に設定されていることを確認してください。これはデフォルトで設定されているので、設定を変更していない場合は、この設定を変更する必要はありません。
  3. sites フレームワーク がインストールされていることを確認してください。

(注意: サイトマップアプリケーションはデータベーステーブルをインストールしません。 INSTALLED_APPS に入れる必要があるのは、 Loader() テンプレートローダーがデフォルトのテンプレートを見つけられるようにするためです)。

初期設定

views.sitemap(request, sitemaps, section=None, template_name='sitemap.xml', content_type='application/xml')

Django サイトでサイトマップの生成を有効にするには、 URLconf に以下の行を追加します:

from django.contrib.sitemaps.views import sitemap

path(
    "sitemap.xml",
    sitemap,
    {"sitemaps": sitemaps},
    name="django.contrib.sitemaps.views.sitemap",
)

これは Django に、クライアントが /sitemap.xml にアクセスしたときにサイトマップを構築するように指示します。

サイトマップファイルの名前は重要ではありませんが、場所は重要です。検索エンジンは、現在のURLレベル以下のサイトマップのリンクだけをインデックスします。例えば、 sitemap.xml がルートディレクトリにある場合、サイト内のどのURLでも参照できます。しかし、サイトマップが /content/sitemap.xml にある場合は、 /content/ で始まるURLのみを参照できます。

サイトマップビューは追加の必須引数を取ります: {'sitemaps': sitemaps}. sitemaps は短いセクションラベル (例えば blognews) を Sitemap クラス (例えば BlogSitemapNewsSitemap) にマップする辞書です。また、 Sitemap クラスの インスタンス (例えば BlogSitemap(some_var)) にマップすることもできます。

Sitemap クラス

Sitemap クラスは、サイトマップ内のエントリの「セクション」を表す Python クラスです。例えば、1 つの Sitemap クラスはブログのすべてのエントリを表し、別のクラスはイベントカレンダー内のすべてのイベントを表すことができます。

最も単純なケースでは、これらのセクションはすべて1つの sitemap.xml にまとめられますが、フレームワークを使って、セクションごとに1つのサイトマップファイルを参照するサイトマップインデックスを生成することもできます。(下記の Creating a sitemap index を参照してください)。

Sitemap クラスは django.contrib.sitemaps.Sitemap のサブクラスでなければなりません。これらはコードベースのどこにあっても構いません。

たとえば、 Entry モデルのブログシステムがあり、サイトマップに個々のブログエントリへのリンクをすべて含めたいとします。サイトマップクラスは次のようになります:

from django.contrib.sitemaps import Sitemap
from blog.models import Entry


class BlogSitemap(Sitemap):
    changefreq = "never"
    priority = 0.5

    def items(self):
        return Entry.objects.filter(is_draft=False)

    def lastmod(self, obj):
        return obj.pub_date

備考:

  • changefreqpriority はそれぞれ <changefreq><priority> 要素に対応するクラス属性です。これらは例の lastmod のように関数として呼び出すことができます。
  • items() はオブジェクトの sequence または QuerySet を返すメソッドです。返されたオブジェクトはサイトマップのプロパティに対応する呼び出し可能なメソッドに渡されます (locationlastmodchangefreqpriority)。
  • lastmoddatetime を返すべきです。
  • この例では location メソッドはありませんが、オブジェクトのURLを指定するために使用できます。デフォルトでは location() は各オブジェクトに対して get_absolute_url() を呼び出し、その結果を返します。

Sitemap クラス リファレンス

class Sitemap

サイトマップ Sitemap クラスは以下のメソッドや属性を定義できます:

items

必須項目. オブジェクトの sequence または QuerySet を返すメソッド。フレームワークはこれらのオブジェクトの タイプ が何であるかについては関心を持ちません; 大切なのはこれらのオブジェクトが location(), lastmod(), changefreq()、および priority() メソッドに渡されることです。

location

オプション。 メソッドまたは属性のいずれか。

メソッドであれば、items() が返すオブジェクトの絶対パスを返す必要があります。

属性である場合、その値は items() が返す すべての オブジェクトに使用する絶対パスを表す文字列でなければなりません。

どちらの場合も、「絶対パス」とは、プロトコルやドメインを含まないURLを意味します。たとえば:

  • 良い例: '/foo/bar/'
  • 悪い例: 'example.com/foo/bar/'
  • 悪い例: 'https://example.com/foo/bar/'

location が提供されていない場合、フレームワークは items() が返す各オブジェクトに対して get_absolute_url() メソッドを呼び出します。

'http' 以外のプロトコルを指定するには、 protocol を使用してください。

lastmod

オプション。 メソッドまたは属性のいずれか。

メソッドであれば、 items() が返すオブジェクトを引数に取り、そのオブジェクトの最終更新日時を datetime として返す必要があります。

属性であれば、その値は items() で返されるすべてのオブジェクトの最終更新日時を表す datetime である必要があります。

サイトマップ内のすべてのアイテムに lastmod がある場合、 views.sitemap() によって生成されるサイトマップには、最新の lastmod に等しい Last-Modified ヘッダーが付きます。リクエストに If-Modified-Since ヘッダーがある場合、Django が適切に応答するようにするには、 ConditionalGetMiddleware をアクティブにします。これにより、サイトマップが変更されていない場合には送信を防ぎます。

paginator

オプション。

このプロパティは、 items() のための Paginator を返します。サイトマップを一括生成する場合は、複数の items() 呼び出しを避けるためにこのキャッシュされたプロパティをオーバーライドすると良いでしょう。

changefreq

オプション。 メソッドまたは属性のいずれか。

メソッドの場合、1つの引数 (items() で返されるオブジェクト) を取るべきであり、そのオブジェクトの変更頻度を文字列で返すべきです。

属性であれば、その値は items() が返す すべての オブジェクトの変更頻度を表す文字列でなければなりません。

changefreq の可能な値は、メソッドの場合も属性の場合も、以下の通りです。

  • 'always'
  • 'hourly'
  • 'daily'
  • 'weekly'
  • 'monthly'
  • 'yearly'
  • 'never'
priority

オプション。 メソッドまたは属性のいずれか。

メソッドであれば、1つの引数 (items() が返すオブジェクト) を取り、そのオブジェクトの優先順位を文字列か浮動小数点数で返します。

属性であれば、その値は、items() で返される すべて のオブジェクトの優先度を表す文字列または浮動小数点数である必要があります。

priority の例として、0.41.0 を指定します。ページのデフォルトの優先度は 0.5 です。詳細については、sitemaps.org documentation を参照してください。

protocol

オプション。

この属性はサイトマップのURLのプロトコル ('http' または 'https') を定義します。設定されていない場合は、サイトマップがリクエストされたプロトコルが使用されます。サイトマップがリクエストのコンテキスト外で作成された場合、デフォルトは 'https' です。

Changed in Django 5.0:

古いバージョンでは、リクエストのコンテキスト外に構築されたサイトマップのデフォルトプロトコルは 'http' でした。

limit

オプション。

この属性はサイトマップの各ページに含まれるURLの最大数を定義します。この値はデフォルト値の 50000 を超えてはいけません。これは Sitemaps protocol で許可されている上限値です。

i18n

オプション。

このサイトマップのURLを LANGUAGES のすべてを使用して生成するかどうかを定義するブール値の属性です。デフォルトは False です。

languages

オプション。

i18n が有効のときに代替リンクを生成するために使用する 言語コードsequence。デフォルトは LANGUAGES

alternates

オプション。

真偽値属性。これを i18n と併用すると、生成される各URLには他言語バージョンを指す代替リンクのリストがあり、 hreflang attribute を使用します。デフォルトは False です。

x_default

オプション。

真偽値属性です。True の場合、 alternates によって生成された代替リンクには、 hreflang="x-default" フォールバックエントリーが含まれ、その値は LANGUAGE_CODE になります。デフォルトは False です。

get_latest_lastmod()

オプション。 lastmod で返される最新の値を返すメソッド。この関数は、 Sitemap インデックス コンテキスト変数lastmod 属性を追加するために使用されます。

デフォルトでは、 get_latest_lastmod() は以下を返します:

  • lastmod が属性の場合:  lastmod
  • lastmod がメソッドの場合、 Sitemap.items() で返されるすべてのアイテムを使用してメソッドを呼び出した結果、最新の lastmod が返されます。
get_languages_for_item(item)
New in Django 4.2.

オプション。 アイテムが表示される言語コードのシーケンスを返すメソッド。デフォルトでは、 get_languages_for_item()languages を返します。

ショートカット

サイトマップフレームワークは、一般的なケースに対する便利なクラスを提供します。

class GenericSitemap(info_dict, priority=None, changefreq=None, protocol=None)

django.contrib.sitemaps.GenericSitemap クラスでは、少なくとも queryset エントリを含む辞書を渡すことで、サイトマップを作成できます。この queryset は、サイトマップのアイテムを生成するために使用されます。また、queryset から取得されたオブジェクトの日付フィールドを指定する date_field エントリを持つこともできます。これは、生成されたサイトマップの lastmod 属性および get_latest_lastmod() メソッドに使用されます。

prioritychangefreqprotocol キーワード引数を使用すると、すべてのURLに対してこれらの属性を指定できます。

カスタマイズ例

以下は GenericSitemap を使用した URLconf の例です:

from django.contrib.sitemaps import GenericSitemap
from django.contrib.sitemaps.views import sitemap
from django.urls import path
from blog.models import Entry

info_dict = {
    "queryset": Entry.objects.all(),
    "date_field": "pub_date",
}

urlpatterns = [
    # some generic view using info_dict
    # ...
    # the sitemap
    path(
        "sitemap.xml",
        sitemap,
        {"sitemaps": {"blog": GenericSitemap(info_dict, priority=0.6)}},
        name="django.contrib.sitemaps.views.sitemap",
    ),
]

静的ビューのサイトマップ

検索エンジンのクローラに、オブジェクト詳細ページでもフラットページでもないビューをインデックスさせたいことがよくあります。その解決策は、 items にこれらのビューの URL 名を明示的に列挙し、サイトマップの location メソッドで reverse() を呼び出すことです。例えば次のようにします:

# sitemaps.py
from django.contrib import sitemaps
from django.urls import reverse


class StaticViewSitemap(sitemaps.Sitemap):
    priority = 0.5
    changefreq = "daily"

    def items(self):
        return ["main", "about", "license"]

    def location(self, item):
        return reverse(item)


# urls.py
from django.contrib.sitemaps.views import sitemap
from django.urls import path

from .sitemaps import StaticViewSitemap
from . import views

sitemaps = {
    "static": StaticViewSitemap,
}

urlpatterns = [
    path("", views.main, name="main"),
    path("about/", views.about, name="about"),
    path("license/", views.license, name="license"),
    # ...
    path(
        "sitemap.xml",
        sitemap,
        {"sitemaps": sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
]

サイトマップインデックスを作成する

views.index(request, sitemaps, template_name='sitemap_index.xml', content_type='application/xml', sitemap_url_name='django.contrib.sitemaps.views.sitemap')

サイトマップフレームワークには、 sitemaps 辞書で定義された各セクションごとに1つずつ、個別のサイトマップファイルを参照するサイトマップインデックスを作成する機能もあります。使用上の唯一の違いは下記です:

上記の例に対する関連するURLconfの行は、次のようになります:

from django.contrib.sitemaps import views

urlpatterns = [
    path(
        "sitemap.xml",
        views.index,
        {"sitemaps": sitemaps},
        name="django.contrib.sitemaps.views.index",
    ),
    path(
        "sitemap-<section>.xml",
        views.sitemap,
        {"sitemaps": sitemaps},
        name="django.contrib.sitemaps.views.sitemap",
    ),
]

これにより、自動的に sitemap.xml ファイルが生成され、 sitemap-flatpages.xmlsitemap-blog.xml の両方が参照されます。 Sitemap クラスと sitemaps 辞書は全く変わりません。

すべてのサイトマップが Sitemap.get_latest_lastmod() で返される lastmod を持っている場合、サイトマップインデックスは最新の lastmod と同じ Last-Modified ヘッダーを持ちます。

サイトマップの URL が 50,000 を超える場合は、インデックスファイルを作成すべきです。この場合、 Django は自動的にサイトマップをページ分割し、インデックスに反映します。

通常のサイトマップビューを使用していない場合 (たとえば、キャッシュデコレータでラップされている場合) は、サイトマップビューに名前を付けて、インデックスビューに sitemap_url_name を渡さなければなりません:

from django.contrib.sitemaps import views as sitemaps_views
from django.views.decorators.cache import cache_page

urlpatterns = [
    path(
        "sitemap.xml",
        cache_page(86400)(sitemaps_views.index),
        {"sitemaps": sitemaps, "sitemap_url_name": "sitemaps"},
    ),
    path(
        "sitemap-<section>.xml",
        cache_page(86400)(sitemaps_views.sitemap),
        {"sitemaps": sitemaps},
        name="sitemaps",
    ),
]

テンプレートをカスタマイズする

サイト上で利用可能な各サイトマップやサイトマップインデックスごとに異なるテンプレートを使用したい場合は、URLconf を介して sitemap ビューや index ビューに template_name パラメータを渡すことで指定できます:

from django.contrib.sitemaps import views

urlpatterns = [
    path(
        "custom-sitemap.xml",
        views.index,
        {"sitemaps": sitemaps, "template_name": "custom_sitemap.html"},
        name="django.contrib.sitemaps.views.index",
    ),
    path(
        "custom-sitemap-<section>.xml",
        views.sitemap,
        {"sitemaps": sitemaps, "template_name": "custom_sitemap.html"},
        name="django.contrib.sitemaps.views.sitemap",
    ),
]

これらのビューは TemplateResponse インスタンスを返し、レンダリング前のレスポンスデータを簡単にカスタマイズできます。詳細は TemplateResponse のドキュメント を参照してください。

コンテキスト変数

テンプレートをカスタマイズする際に、 index()sitemap() ビューには、以下のコンテキスト変数に依存できます。

インデックス

変数 sitemaps は各サイトマップの locationlastmod 属性を含むオブジェクトのリストです。各URLは以下の属性を持ちます:

  • location: サイトマップの場所 (URLとページ)。
  • lastmod: 各サイトマップに対して get_latest_lastmod() メソッドによって設定されます。

サイトマップ

変数 urlset は、サイトマップに表示されるべきURLのリストです。各URLは、 Sitemap クラスで定義された属性を公開しています。

  • alternates
  • changefreq
  • item
  • lastmod
  • location
  • priority

alternates 属性は、 i18nalternates が有効になっている場合に利用可能です。それは、各URLに対してオプションの x_default フォールバックを含む、他の言語バージョンのリストです。各代替バージョンは、locationlang_code キーを持つ辞書です。

各URLに item 属性が追加され、Google news sitemaps のようなテンプレートをより柔軟にカスタマイズできるようになりました。Sitemapの items()publication_datatags フィールドを持つアイテムのリストを返すと仮定すると、このようにGoogleニュース互換のサイトマップが生成されます:

<?xml version="1.0" encoding="UTF-8"?>
<urlset
  xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
{% spaceless %}
{% for url in urlset %}
  <url>
    <loc>{{ url.location }}</loc>
    {% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
    {% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
    {% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
    <news:news>
      {% if url.item.publication_date %}<news:publication_date>{{ url.item.publication_date|date:"Y-m-d" }}</news:publication_date>{% endif %}
      {% if url.item.tags %}<news:keywords>{{ url.item.tags }}</news:keywords>{% endif %}
    </news:news>
   </url>
{% endfor %}
{% endspaceless %}
</urlset>
Back to Top