サイトマップフレームワーク
Djangoには、 sitemap XMLファイルを作成するための高レベルのサイトマップ生成フレームワークが付属しています。
概要
サイトマップは、Webサイト上のXMLファイルであり、検索エンジンのインデクサーに、ページが変更される頻度と、特定のページがサイトの他のページと比較してどの程度「重要」であるかを通知します。 この情報は、検索エンジンがサイトのインデックスを作成するのに役立ちます。
Djangoサイトマップフレームワークは、この情報をPythonコードで表現できるようにすることで、このXMLファイルの作成を自動化します。
これは、Djangoのシンジケーションフレームワークとほとんど同じように機能します。 サイトマップを作成するには、 Sitemap クラスを記述し、 URLconf でそれをポイントします。
インストール
サイトマップアプリをインストールするには、次の手順に従います。
'django.contrib.sitemaps'
を:setting: `INSTALLED_APPS` 設定に追加します。- :setting: `TEMPLATES` 設定に、
APP_DIRS
オプションがTrue
に設定されているDjangoTemplates
バックエンドが含まれていることを確認してください。 デフォルトでそこにあるので、その設定を変更した場合にのみこれを変更する必要があります。 - サイトフレームワークがインストールされていることを確認してください。
(注:サイトマップアプリケーションはデータベーステーブルをインストールしません。 :setting: `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')
これは、クライアントが/sitemap.xml
にアクセスしたときにサイトマップを作成するようにDjangoに指示します。
サイトマップファイルの名前は重要ではありませんが、場所は重要です。 検索エンジンは、現在のURLレベル以下のサイトマップ内のリンクのみをインデックスに登録します。 たとえば、sitemap.xml
がルートディレクトリにある場合、サイト内の任意のURLを参照している可能性があります。 ただし、サイトマップが/content/sitemap.xml
にある場合は、/content/
で始まるURLのみを参照できます。
サイトマップビューには、{'sitemaps': sitemaps}
という追加の必須引数が必要です。 sitemaps
は、短いセクションラベル(blog
またはnews
など)をそのサイトマップクラス( [など)にマップする辞書である必要があります。 X137X]またはNewsSitemap
)。 また、サイトマップクラスのインスタンス(BlogSitemap(some_var)
など)にマップすることもできます。
Sitemapクラス
サイトマップクラスは、サイトマップのエントリの「セクション」を表すPythonクラスです。 たとえば、1つの Sitemap クラスは、ブログのすべてのエントリを表すことができ、別のクラスは、イベントカレンダーのすべてのイベントを表すことができます。
最も単純なケースでは、これらすべてのセクションが1つのsitemap.xml
にまとめられますが、フレームワークを使用して、セクションごとに1つずつ個々のサイトマップファイルを参照するサイトマップインデックスを生成することもできます。 (以下のサイトマップインデックスの作成を参照してください。)
サイトマップクラスは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()は、オブジェクトのシーケンスまたは
QuerySet
を返すメソッドです。 返されたオブジェクトは、サイトマッププロパティ( location 、 lastmod 、 changefreq 、および priority )に対応する呼び出し可能なメソッドに渡されます。 - lastmod は
datetime
を返すはずです。 - この例には location メソッドはありませんが、オブジェクトのURLを指定するためにメソッドを指定できます。 デフォルトでは、 location()は各オブジェクトで
get_absolute_url()
を呼び出し、結果を返します。
Sitemapクラスリファレンス
- class Sitemap
Sitemap
クラスは、次のメソッド/属性を定義できます。- items
必須。オブジェクトのシーケンスまたは
QuerySet
を返すメソッド。 フレームワークは、オブジェクトのタイプが何であるかを気にしません。 重要なのは、これらのオブジェクトが location()、 lastmod()、 changefreq()、および priority()に渡されることです。メソッド。
- location
オプション。メソッドまたは属性のいずれか。
メソッドの場合は、 items()によって返される特定のオブジェクトの絶対パスを返す必要があります。
属性の場合、その値は、 items()によって返されるすべてのオブジェクトに使用する絶対パスを表す文字列である必要があります。
どちらの場合も、「絶対パス」とは、プロトコルまたはドメインを含まないURLを意味します。 例:
良い:
'/foo/bar/'
悪い例:
'example.com/foo/bar/'
location が指定されていない場合、フレームワークは items()によって返される各オブジェクトで
get_absolute_url()
メソッドを呼び出します。'http'
以外のプロトコルを指定するには、プロトコルを使用します。
- lastmod
オプション。メソッドまたは属性のいずれか。
メソッドの場合は、1つの引数( items()によって返されるオブジェクト)を取り、そのオブジェクトの最終変更日時を
datetime
として返す必要があります。属性の場合、その値は、 items()によって返されるすべてのオブジェクトの最終変更日時を表す
datetime
である必要があります。サイトマップ内のすべてのアイテムに lastmod がある場合、 views.sitemap()によって生成されたサイトマップには、最新の
lastmod
と等しいLast-Modified
ヘッダーがあります。 ]。 ConditionalGetMiddleware をアクティブ化すると、DjangoがIf-Modified-Since
ヘッダーを使用してリクエストに適切に応答するようになり、サイトマップが変更されていない場合は送信されなくなります。
- changefreq
オプション。メソッドまたは属性のいずれか。
メソッドの場合は、1つの引数( items()によって返されるオブジェクト)を取り、そのオブジェクトの変更頻度を文字列として返す必要があります。
属性の場合、その値は、 items()によって返される every オブジェクトの変更頻度を表す文字列である必要があります。
メソッドまたは属性のどちらを使用する場合でも、 changefreq に指定できる値は次のとおりです。
'always'
'hourly'
'daily'
'weekly'
'monthly'
'yearly'
'never'
- priority
オプション。メソッドまたは属性のいずれか。
メソッドの場合は、1つの引数( items()によって返されるオブジェクト)を取り、そのオブジェクトの優先度を文字列または浮動小数点数として返す必要があります。
属性の場合、その値は、 items()によって返されるすべてのオブジェクトの優先度を表す文字列またはfloatのいずれかである必要があります。
priority の値の例:
0.4
、1.0
。 ページのデフォルトの優先度は0.5
です。 詳細については、 sitemaps.orgのドキュメントを参照してください。
- protocol
オプション。
この属性は、サイトマップ内のURLのプロトコル(
'http'
または'https'
)を定義します。 設定されていない場合は、サイトマップが要求されたプロトコルが使用されます。 サイトマップがリクエストのコンテキスト外で作成されている場合、デフォルトは'http'
です。
- limit
オプション。
この属性は、サイトマップの各ページに含まれるURLの最大数を定義します。 その値は、サイトマッププロトコルで許可されている上限である
50000
のデフォルト値を超えてはなりません。
- i18n
オプション。
このサイトマップのURLをすべての:setting: `LANGUAGES` を使用して生成するかどうかを定義するブール属性。 デフォルトは
False
です。
ショートカット
サイトマップフレームワークは、一般的なケースに便利なクラスを提供します。
- class GenericSitemap(info_dict, priority=None, changefreq=None, protocol=None)
django.contrib.sitemaps.GenericSitemap クラスを使用すると、少なくとも
queryset
エントリを含む必要のある辞書を渡すことでサイトマップを作成できます。 このクエリセットは、サイトマップのアイテムを生成するために使用されます。 また、queryset
から取得したオブジェクトの日付フィールドを指定するdate_field
エントリが含まれる場合もあります。 これは、生成されたサイトマップの 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'),
]
静的ビューのサイトマップ
多くの場合、検索エンジンのクローラーに、オブジェクトの詳細ページでもフラットページでもないビューのインデックスを作成する必要があります。 解決策は、これらのビューのURL名をitems
に明示的にリストし、サイトマップの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では、 django.contrib.sitemaps.views.index()と django.contrib.sitemaps.views.sitemap()の2つのビューを使用します。
- django.contrib.sitemaps.views.sitemap()ビューは、
section
キーワード引数を取る必要があります。
上記の例では、関連するURLconf行は次のようになります。
from django.contrib.sitemaps import views
urlpatterns = [
path('sitemap.xml', views.index, {'sitemaps': sitemaps}),
path('sitemap-<section>.xml', views.sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap'),
]
これにより、sitemap-flatpages.xml
とsitemap-blog.xml
の両方を参照するsitemap.xml
ファイルが自動的に生成されます。 Sitemap クラスとsitemaps
dictはまったく変更されません。
サイトマップの1つに50,000を超えるURLがある場合は、インデックスファイルを作成する必要があります。 この場合、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'),
]
テンプレートのカスタマイズ
サイトで利用可能なサイトマップまたはサイトマップインデックスごとに異なるテンプレートを使用する場合は、template_name
パラメータをsitemap
およびindex
ビューに渡すことで指定できます。 URLconf:
from django.contrib.sitemaps import views
urlpatterns = [
path('custom-sitemap.xml', views.index, {
'sitemaps': sitemaps,
'template_name': 'custom_sitemap.html'
}),
path('custom-sitemap-<section>.xml', views.sitemap, {
'sitemaps': sitemaps,
'template_name': 'custom_sitemap.html'
}, name='django.contrib.sitemaps.views.sitemap'),
]
これらのビューは TemplateResponse インスタンスを返し、レンダリング前に応答データを簡単にカスタマイズできます。 詳細については、 TemplateResponseのドキュメントを参照してください。
索引
変数sitemaps
は、各サイトマップへの絶対URLのリストです。
サイトマップ
変数urlset
は、サイトマップに表示されるURLのリストです。 各URLは、サイトマップクラスで定義されている属性を公開します。
changefreq
item
lastmod
location
priority
item
属性が各URLに追加され、 Googleニュースサイトマップなどのテンプレートをより柔軟にカスタマイズできるようになりました。 サイトマップの items()がpublication_data
とtags
フィールドを持つアイテムのリストを返すと仮定すると、次のようなものが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>
Googleにpingを送信
サイトマップが変更されたときにGoogleに「ping」して、サイトのインデックスを再作成するように通知することをお勧めします。 サイトマップフレームワークは、まさにそれを行うための関数を提供します: django.contrib.sitemaps.ping_google()。
- ping_google(sitemap_url=None, ping_url=PING_URL, sitemap_uses_https=True)
ping_google
は、次のオプションの引数を取ります。sitemap_url
-サイトのサイトマップへの絶対パス(例:'/sitemap.xml'
)。 この引数が指定されていない場合、ping_google
は、URLconfで逆引き参照を実行して、サイトマップを把握しようとします。ping_url
-デフォルトはGoogleのPingツール: https://www.google.com/webmasters/tools/ping。sitemap_uses_https
-サイトでhttps
ではなくhttp
を使用している場合は、False
に設定します。
ping_google()は、サイトマップURLを特定できない場合、例外
django.contrib.sitemaps.SitemapNotFound
を発生させます。バージョン2.2の新機能:
sitemap_uses_https
引数が追加されました。 古いバージョンのDjangoは、サイトマップのURLに常にhttp
を使用します。
ping_google()を呼び出す便利な方法の1つは、モデルのsave()
メソッドからです。
from django.contrib.sitemaps import ping_google
class Entry(models.Model):
# ...
def save(self, force_insert=False, force_update=False):
super().save(force_insert, force_update)
try:
ping_google()
except Exception:
# Bare 'except' because we could get a variety
# of HTTP-related exceptions.
pass
ただし、より効率的な解決策は、cronスクリプトまたはその他のスケジュールされたタスクから ping_google()を呼び出すことです。 この関数はGoogleのサーバーにHTTPリクエストを送信するため、save()
を呼び出すたびにそのネットワークオーバーヘッドを導入したくない場合があります。
manage.pyを介してGoogleにpingを実行します
サイトマップアプリケーションがプロジェクトに追加されたら、ping_google
管理コマンドを使用してGoogleにpingを実行することもできます。
python manage.py ping_google [/sitemap.xml]
バージョン2.2の新機能。
サイトマップでhttps
ではなくhttp
を使用している場合は、このオプションを使用してください。