This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 3 years have passed since last update.

[Day 28]サイトマップを作成する

Last updated at Posted at 2021-02-06

February 6, 2021
←前回:Day 27 ページネーションを使う

「Djangoを学びたい」とのことでありましたら[Day 1]Djangoの開発環境から読むことをおすすめします。

#はじめに
SEO対策として検索エンジンにウェブサイトの更新を通知するためサイトマップを用意したいケースも多いと思います。今回はDjangoを用いてサイトマップを動的に生成する方法を見ていきます。

準備

まずsettings.pyを変更する必要があります。

settings.py

  INSTALLED_APPS = [
      'django.contrib.admin',
      'django.contrib.auth',
      'django.contrib.contenttypes',
      'django.contrib.sessions',
      'django.contrib.messages',
      'django.contrib.staticfiles',
+     'django.contrib.sites',
+     'django.contrib.sitemaps',
      'debug_toolbar',
      'base',
      'thread',
      'api',
      'search',
  ]

+ SITE_ID = 1

次にデータベースのマイグレーションをします。


(venv)$ ./manage.py migrate

管理画面にアクセスしてドメイン名と表示名を変更します。今回はmydomain.comに修正しました。このサイトオブジェクトのIDが先程settings.pyで設定したSITE_IDと一致している必要があります。

image.png

Sitemap継承クラスを作る

ではサイトマップを作っていきましょう。DjangoにおいてサイトマップはSitemapクラスを継承したクラスにて作成します。thread/sitemaps.pyを作成します。尚、sitemaps.pyはDjangoで決まっているファイルではありませんので別の名前でもいいですし、他のファイルに書いても構いません。

thread/sitemaps.py

from django.contrib.sitemaps import Sitemap
from django.shortcuts import resolve_url

from . models import Topic, Category

class TopicSitemap(Sitemap):
    priority = 0.5
    changefreq = 'always'

    def items(self):
        return Topic.objects.all()

    def location(self, obj):
        return resolve_url('thread:topic', pk=obj.id)

class CategorySitemap(Sitemap):
    priority = 0.5
    changefreq = 'never'

    def items(self):
        return Category.objects.all()

    def location(self, obj):
        return resolve_url('thread:category', url_code=obj.url_code)

Sitemapクラスを継承したクラスを作成しています。このクラスではサイトマップを作成に必要な情報をクラスの属性として与えます。この際、静的な情報はクラス変数、動的な情報は関数を使って指定出来るようになっています。

指定できる属性は以下です。

items [必須]ページのオブジェクト。イテレータブルなオブジェクトを指定する
location [オプション]itemsのURL
lastmod [オプション]ページ更新日時
changefreq [オプション]ページの更新頻度
priority [オプション]ページの重要度0〜1
limit [オプション]ページネーションの区切り。デフォルトは50000
protocol [オプション]httpプロトコル。デフォルトはhttp
i18n [オプション]URL表示に設定言語を適用するか True/False

まず、items()メソッドでトピックのリストを与えています。この関数が返すイテレータブルなitemsの1つ1つに対してサイトマップが生成されます。ではこのitemsの要素であるitemのURLのを指定するためにlocation関数でURLを指定しましょう。トピックのURLは動的に変更するのでlocationは関数で与えます。このようにitemsで指定したリストの1要素を仮引数とする関数を作ることで動的なサイトマップを生成できます。

カテゴリー用のサイトマップも同様です。CategorySitemapクラスを作成して要素を指定しています。カテゴリーの場合はurl_codeを指定することに注意して下さい。

では、次に静的なページである利用規約やプライバシーポリシーについて見ていきましょう。これらのページは動的要素がないために非常に簡単です。base/sitemaps.pyを生成しましょう。

sitemaps.py

from django.contrib.sitemaps import Sitemap
from django.shortcuts import resolve_url

class BaseSitemap(Sitemap):

    def items(self):
        items = [
            'base:top',
            'base:policy',
            'base:terms',
        ]
        return items

    def location(self, obj):
        return resolve_url(obj)

    def changefreq(self, obj):
        if obj == 'base:top':
            return 'always'
        return 'never'

    def priority(self, obj):
        if obj == 'base:top':
            return 0.8
        return 0.1

基本的な考え方はthread/sitemaps.pyと同じです。ただitemsで’base:policy’のようにページのショートカット名でリストを生成することで効率的にサイトマップを生成することができます。上記でクラス変数として指定した属性についても関数で指定しています。両者を比べると理解がより進むのではないでしょうか。

URLの設定

では、作成したサイトマップを表示してみましょう。ここから先はmysite/urls.pyを変更していきます。

mysite/urls.py

  from django.contrib import admin, auth
  from django.urls import path, include
  from django.conf import settings
  from django.contrib.sitemaps.views import sitemap

+ from thread.sitemaps import TopicSitemap, CategorySitemap
+ from base.sitemaps import BaseSitemap

+ sitemaps = {
+     'topic': TopicSitemap,
+     'cateogry': CategorySitemap,
+     'base': BaseSitemap,
+ }

  urlpatterns = [
      path('admin/', admin.site.urls),
      path('accounts/', include('django.contrib.auth.urls')),
      path('', include('base.urls')),
      path('thread/', include('thread.urls')),
      path('api/', include('api.urls')),
      path('search/', include('search.urls')),
+     path('sitemap.xml', sitemap, {'sitemaps': sitemaps}),
  ]

  if settings.DEBUG:
      import debug_toolbar
      urlpatterns = [
          path('__debug__/', include(debug_toolbar.urls)),
      ] + urlpatterns

このように各アプリケーションでSitemap継承クラスを作成し、urls.pyでまとめるというのはDjangoのルールではないですが、分かりやすいので筆者は気に入っています。

では確認してみましょう。localhost:8080/sitemap.xmlにアクセスします。

image.png

終わりに

今日は天気がよく花粉がよく飛んでいるらしいです。
私は花粉のニュースを見ると花粉症になるのでニュースは元から見ていませんが、これからも見ないようにしたいです。

それではまたまた

←前回:Day 27 ページネーションを使う
→次回:Day 29 Djangoでメールを送信する

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up