Django - Sitemap Tutorial (Python)
How to create XML sitemaps with Django sitemap framework.
Updated Nov 3, 2023

Prerequisities

Use this to setup a base project:

Django - Blog App Tutorial (Python)

Settings

Edit mysite/settings.py and add these lines:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites', # here
    'django.contrib.sitemaps', # here
    'blog',
]

SITE_ID = 1 # here
  • django.contrib.sites enables the sites framework. The sitemap framework needs it to work properly.
  • django.contrib.sitemaps enables the sitemap framework.
  • "1" is the database ID of the default Site object. This association is made to connect this particular settings file with a Site object.

Update Post Model

Edit blog/models.py and add a modified field to it. Make sure that your model has the get_absolute_url method:

from django.db import models
from django.urls import reverse


class Post(models.Model):
    title = models.CharField(max_length=255, blank=False, default='')
    body = models.TextField(blank=False, default='')
    slug = models.SlugField(max_length=255, blank=False, unique=True)
    modified = models.DateTimeField(auto_now=True) # here

    def __str__(self):
        return self.title

    # here
    def get_absolute_url(self):
        return reverse('blog:post_detail', args=[self.slug])
  • The modified field is used for the sitemap lastmod attribute.
  • auto_now=True is used to specify that the field should be automatically set to the current date and time when the object is created or updated.

Run migrations:

python manage.py makemigrations
python manage.py migrate

Sitemap For Blog Posts

Edit mysite/urls.py:

from django.contrib import admin
from django.urls import include, path
from blog.models import Post # here
from django.contrib.sitemaps import GenericSitemap # here
from django.contrib.sitemaps.views import sitemap # here

# here
sitemaps = {
    'blog': GenericSitemap({
        'queryset': Post.objects.all(),
        'date_field': 'modified',
    }),
}

urlpatterns = [
    path('blog/', include('blog.urls')),
    path('admin/', admin.site.urls),
    # here
    path('sitemap.xml', sitemap,
         {'sitemaps': sitemaps},
         name='django.contrib.sitemaps.views.sitemap'),
]
  • The GenericSitemap convenience class allows you to create basic sitemaps by passing it a queryset entry.

Visit http://127.0.0.1:8000/sitemap.xml and you should see something like this:

<urlset xmlns="http://www.sitemaps.org...">
<url>
<loc>http://example.com/blog/how-to-make-money/</loc>
<lastmod>2023-11-03</lastmod>
</url>
</urlset>

Sitemap For Static Pages

Let's add /about/ page to the sitemap.

Edit mysite/urls.py and make these changes:

from django.contrib import admin
from django.urls import include, path, reverse # here
from blog.models import Post
from django.contrib.sitemaps import GenericSitemap
from django.contrib.sitemaps.views import sitemap
from django.contrib.sitemaps import Sitemap # here
from django.views.generic import TemplateView # here


# here
class StaticViewSitemap(Sitemap):
    def items(self):
        return ['about']

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

sitemaps = {
    'blog': GenericSitemap({
        'queryset': Post.objects.all(),
        'date_field': 'modified',
    }),
    'static': StaticViewSitemap, # here
}

urlpatterns = [
    path('blog/', include('blog.urls')),
    path('admin/', admin.site.urls),
    # here:
    path('about/', TemplateView.as_view(template_name='about.html'), name='about'),
    path('sitemap.xml', sitemap,
         {'sitemaps': sitemaps},
         name='django.contrib.sitemaps.views.sitemap'),
]
  • The Sitemap class provides more control over the creation of sitemaps, but it requires you to create a dedicated class.

Create templates/about.html:

<div class="about">
    <h1>About</h1>
    <p>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. 
    </p>
</div>

Visit /sitemap.xml:

<urlset xmlns="http://www.sitemaps...">
<url>
<loc>http://example.com/blog/how-to-make-money/</loc>
<lastmod>2023-11-03</lastmod>
</url>
<url>
<loc>http://example.com/about/</loc>
</url>
</urlset>

Domain

In production, make sure to update the Site object to match your domain:

More Django Tutorials