[Django] サイトマップを出力する方法

Webサイトを運営する際、サイトマップを作成すると色々な恩恵を受けることができますが、フォーマットに従ってXMLファイルを作成するのは結構面倒です。Djangoには「sitemap framework」というフレームワークがあり、これを使うとそのサイトマップを簡単に出力することができます。

目次

  1. はじめに
  2. サイトマップの作成
  3. サイトマップインデックスの作成

はじめに

この例では「myapp」という、一覧表示と詳細表示があるアプリを使います。

myapp/views.py

import logging
from django.shortcuts import render_to_response, redirect
from django.core.urlresolvers import reverse
from myapp.models import Item

logger = logging.getLogger(__name__)

def index(request):
    items = Item.objects.all()
    return render_to_response('myapp/index.html', dict(items=items))

def item(request, item_id):
    item = Item.objects.get(id=item_id)
    return render_to_response('myapp/item.html', dict(item=item))

myapp/models.py

from django.db import models

# Create your models here.

class Item(models.Model):
    name = models.CharField(max_length=100)
    price = models.PositiveIntegerField()
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

myapp/urls.py

from django.conf.urls import patterns, include, url

urlpatterns = patterns('myapp.views',
    url(r'^$', 'index'),
    url(r'^item/(?P<item_id>d+)$', 'item'),
)

↑ 目次に戻る

サイトマップの作成

Djangoでサイトマップを出力するには、「settings.py」の「INSTALLED_APPS」に「django.contrib.sitemaps」を追加します。また、sitemap frameworkを使うには「sites framework」を有効にする必要があるので、使っていない場合はその設定も行います。※ sites frameworkを使うのが初めての場合、syncdbで「django_site」テーブルを作成する必要があります。

settings.py

INSTALLED_APPS = (
    ...
    'django.contrib.sites',
    'django.contrib.sitemaps',
    ...
)

SITE_ID = 1

「settings.py」を修正したら、次はサイトマップの出力ルールを決定するpyファイルを作成します。これは任意の場所でいいのですが、今回は「myapps/sitemaps.py」という位置に作成します。ここで一覧表示(IndexSitemap)と詳細表示(ItemSitemap)のサイトマップ出力ルールを決定します。

myapp/sitemaps.py

# -*- coding: utf-8 -*-
from django.contrib.sitemaps import Sitemap
from django.core.urlresolvers import reverse
from myapp.models import Item


class IndexSitemap(Sitemap):
    # サイトマップの「changefreq」・「priority」タグに何を出力するかを決めます。
    changefreq = 'daily'
    priority = 1.0
    protocol = 'http'

    def items(self):
        # indexページは1ページしかないので、サイズ1のリストを返します。('index'という文字列は適当です)
        return ['index']

    def location(self, obj):
        # サイトマップの「loc」タグに出力する内容を決定します。
        return reverse('myapp.views.index')

    def lastmod(self, obj):
        items = Item.objects.all().order_by('-updated')
        if items:
            # 商品が存在すれば、その最大値を最終更新時刻にします。
            return items[0].updated


class ItemSitemap(Sitemap):
    changefreq = 'weekly'
    priority = 0.5
    protocol = 'http'

    def items(self):
        # 商品をすべてサイトマップに載せます。
        return Item.objects.all()

    def location(self, obj):
        # サイトマップの「loc」タグに出力する内容を決定します。
        # なお、このobjはitemsで返したリストの、各オブジェクトになります。
        return reverse('myapp.views.item', args=[obj.id])

    def lastmod(self, obj):
        # Itemモデルのupdatedをlastmodに使います。
        return obj.updated

最後に「urls.py」を編集して、サイトマップを表示できるようにします。※ ここで編集するurls.pyは「myapps/urls.py」ではなく、「settings.py」に指定した「urls.py」です。

urls.py

from django.conf.urls import patterns, include, url
from myapp import sitemaps as myapp_sitemaps

sitemaps = {
    'index': myapp_sitemaps.IndexSitemap,
    'items': myapp_sitemaps.ItemSitemap,
}


urlpatterns = patterns('',
    url(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
    url(r'^myapp/', include('myapp.urls')),
)

これで「ドメイン名」/sitemap.xmlにアクセスすると、サイトマップが表示されます。

表示されるサイトマップ

※ 「loc」のドメインの部分には、「django_site」テーブルの「domain」カラムが使われるので、本番環境で使用する場合は更新しておく必要があります。

UPDATE django_site SET domain='localhost:8000' WHERE id=1;

↑ 目次に戻る

サイトマップインデックスの作成

「sitemap framework」にはサイトマップを分割して表示する機能もあります。その場合「sitemap」がサイトマップインデックスになり、その中に各サイトマップのURLが記述されています。やり方は簡単で、「urls.py」を修正するだけです。

urls.py

from django.conf.urls import patterns, include, url
from myapp import sitemaps as myapp_sitemaps

sitemaps = {
    'index': myapp_sitemaps.IndexSitemap,
    'items': myapp_sitemaps.ItemSitemap,
}

urlpatterns = patterns('',
    # url(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
    url(r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}),
    url(r'^sitemap-(?P<section>.+).xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
    url(r'^myapp/', include('myapp.urls')),
)

サイトマップインデックス
各サイトマップ

このサイトマップインデックスを使用している場合、一つのサイトマップに出力するURLが50,000件を超えた場合は自動的に分割されます。

50,000件を超えた場合のサイトマップインデックス

↑ 目次に戻る

この記事が役に立った場合、シェアしていただけると励みになります!!