Skip to main content

Automating Sitemaps with GenericSitemap

By using the GenericSitemap utility in django.contrib.sitemaps, you can automate the generation of XML sitemaps for your Django models without writing custom sitemap classes. This tutorial walks you through exposing a model's data to search engines using a QuerySet.

Prerequisites

To use sitemaps in this project, ensure your settings.py includes the following in INSTALLED_APPS:

INSTALLED_APPS = [
'django.contrib.sitemaps',
'django.contrib.sites',
# ... your other apps
]

SITE_ID = 1

The sites framework is required because sitemaps need to generate absolute URLs including the domain name.

Step 1: Prepare Your Model

GenericSitemap relies on your model having a get_absolute_url() method to determine the location of each item. We will use the TestModel from tests/sitemaps_tests/models.py as our example.

from django.db import models

class TestModel(models.Model):
name = models.CharField(max_length=100)
lastmod = models.DateTimeField(null=True)

def get_absolute_url(self):
return "/testmodel/%s/" % self.id

The lastmod field is optional but highly recommended as it allows search engines to know when your content was last updated.

Step 2: Define the Configuration Dictionary

The GenericSitemap class requires an info_dict that specifies which records to include. At a minimum, this dictionary must contain a queryset.

Create a dictionary that selects the objects you want to appear in the sitemap:

from .models import TestModel

info_dict = {
"queryset": TestModel.objects.all(),
"date_field": "lastmod", # Optional: maps to the <lastmod> tag
}

If you provide date_field, GenericSitemap will automatically use that field's value for the <lastmod> tag in the XML output.

Step 3: Instantiate the GenericSitemap

Now, instantiate GenericSitemap using the info_dict. You can also provide global metadata like priority and changefreq directly to the constructor.

from django.contrib.sitemaps import GenericSitemap

# Create the sitemap instance
blog_sitemap = GenericSitemap(
info_dict,
priority=0.6,
changefreq="monthly"
)

# Map it to a section name
sitemaps = {
"blog": blog_sitemap,
}

In this example, every item in the TestModel queryset will be assigned a priority of 0.6 and a change frequency of monthly.

Step 4: Configure the URL Route

Finally, wire the sitemap into your urls.py using the django.contrib.sitemaps.views.sitemap view. This view takes the sitemaps dictionary you created in the previous step.

from django.urls import path
from django.contrib.sitemaps import views

urlpatterns = [
path(
"sitemap.xml",
views.sitemap,
{"sitemaps": sitemaps},
name="django.contrib.sitemaps.views.sitemap"
),
]

Verifying the Result

Once configured, navigate to /sitemap.xml in your browser. You should see an XML structure similar to this:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://example.com/testmodel/1/</loc>
<lastmod>2023-10-27</lastmod>
<changefreq>monthly</changefreq>
<priority>0.6</priority>
</url>
</urlset>

Important Considerations

  • QuerySet Evaluation: GenericSitemap.items() calls self.queryset.filter() to ensure the QuerySet is cloned and not evaluated prematurely.
  • Last Modified Logic: The get_latest_lastmod() method in GenericSitemap automatically finds the most recent date in your date_field to populate the sitemap index headers if needed.
  • Site Framework: If you do not have the sites framework configured, the sitemap view will fail when trying to resolve the domain for the <loc> tags.