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 aSite
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 sitemaplastmod
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 aqueryset
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: