サイトマップ・フレームワーク¶
Djangoには、 sitemap XML ファイルを作成するための高レベルなサイトマップ生成フレームワークが付属しています。
概要¶
サイトマップとは、検索エンジンのインデクサーに、ページの変更頻度や、あるページがサイト内の他のページと比較してどの程度「重要」であるかを伝える、ウェブサイト上のXMLファイルのことです。この情報は、検索エンジンがあなたのサイトをインデックスするのに役立ちます。
Django サイトマップフレームワークは、この情報を Python コードで表現することで、XML ファイルの作成を自動化します。
これは Django の 配信 (syndication) フレームワーク のように動作します。サイトマップを作成するには、 Sitemap
クラスを書き、 URLconf の中でそれを指定します。
インストール¶
サイトマップ アプリをインストールするには、以下の手順に従ってください。
'django.contrib.sitemaps'
をINSTALLED_APPS
設定に追加します。TEMPLATES
設定には、DjangoTemplates
バックエンドが含まれており、APP_DIRS
オプションがTrue
に設定されていることを確認してください。これはデフォルトで設定されているので、設定を変更していない場合は、この設定を変更する必要はありません。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
は短いセクションラベル (例えば blog
や news
) を Sitemap
クラス (例えば BlogSitemap
や NewsSitemap
) にマップする辞書です。また、 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
備考:
changefreq
とpriority
はそれぞれ<changefreq>
と<priority>
要素に対応するクラス属性です。これらは例のlastmod
のように関数として呼び出すことができます。items()
はオブジェクトの sequence またはQuerySet
を返すメソッドです。返されたオブジェクトはサイトマップのプロパティに対応する呼び出し可能なメソッドに渡されます (location
、lastmod
、changefreq
、priority
)。lastmod
はdatetime
を返すべきです。- この例では
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.4
、1.0
を指定します。ページのデフォルトの優先度は0.5
です。詳細については、sitemaps.org documentation を参照してください。
-
protocol
¶ オプション。
この属性はサイトマップのURLのプロトコル (
'http'
または'https'
) を定義します。設定されていない場合は、サイトマップがリクエストされたプロトコルが使用されます。サイトマップがリクエストのコンテキスト外で作成された場合、デフォルトは'https'
です。Changed in Django 5.0:古いバージョンでは、リクエストのコンテキスト外に構築されたサイトマップのデフォルトプロトコルは
'http'
でした。
-
limit
¶ オプション。
この属性はサイトマップの各ページに含まれるURLの最大数を定義します。この値はデフォルト値の
50000
を超えてはいけません。これは Sitemaps protocol で許可されている上限値です。
-
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)[ソース]¶ オプション。 アイテムが表示される言語コードのシーケンスを返すメソッド。デフォルトでは、
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()
メソッドに使用されます。priority
、changefreq
、protocol
キーワード引数を使用すると、すべての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 で 2 つのビューを使用しています:
django.contrib.sitemaps.views.index()
とdjango.contrib.sitemaps.views.sitemap()
。 django.contrib.sitemaps.views.sitemap()
ビューは、section
キーワード引数を受け取るべきです。
上記の例に対する関連する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.xml
と sitemap-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 のドキュメント を参照してください。
インデックス¶
変数 sitemaps
は各サイトマップの location
と lastmod
属性を含むオブジェクトのリストです。各URLは以下の属性を持ちます:
location
: サイトマップの場所 (URLとページ)。lastmod
: 各サイトマップに対してget_latest_lastmod()
メソッドによって設定されます。
サイトマップ¶
変数 urlset
は、サイトマップに表示されるべきURLのリストです。各URLは、 Sitemap
クラスで定義された属性を公開しています。
alternates
changefreq
item
lastmod
location
priority
alternates
属性は、 i18n
と alternates
が有効になっている場合に利用可能です。それは、各URLに対してオプションの x_default
フォールバックを含む、他の言語バージョンのリストです。各代替バージョンは、location
と lang_code
キーを持つ辞書です。
各URLに item
属性が追加され、Google news sitemaps のようなテンプレートをより柔軟にカスタマイズできるようになりました。Sitemapの items()
が publication_data
と tags
フィールドを持つアイテムのリストを返すと仮定すると、このようにGoogleニュース互換のサイトマップが生成されます:
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:news="https://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>