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()callsself.queryset.filter()to ensure the QuerySet is cloned and not evaluated prematurely. - Last Modified Logic: The
get_latest_lastmod()method inGenericSitemapautomatically finds the most recent date in yourdate_fieldto populate the sitemap index headers if needed. - Site Framework: If you do not have the
sitesframework configured, the sitemap view will fail when trying to resolve the domain for the<loc>tags.