OverIQ.com

Creating Sitemaps in Django

Last updated on July 27, 2020


A Sitemap is just a list of links in a website which you want a search engine to crawl and thus index. In addition to that, a sitemap is also used to tell following information about the pages:

  1. How frequently the page changes.
  2. Last modification date of the page.
  3. Priority of the URL in relation to other URLs.

Types of Sitemap #

Sitemaps are of two types:

  1. HTML Sitemap.
  2. XML Sitemap.

HTML Sitesmap #

An HTML Sitemap is designed for the users to help them navigate the site. To create an HTML sitemap simply list your URLs using the <ol> or <ul> tags, like this:

1
2
3
4
5
6
7
8
9
<h2>DjangoBin Sitemap</h2>

<ul>
    <li><a href="http://example.com">Home</a></li>
    <li><a href="http://example.com/blog">Blog</a></li>
    <li><a href="http://example.com/contact">contact</a></li>
    <li><a href="http://example.com/careers">Careers</a></li>
    <li><a href="http://example.com/eula">EULA</a></li>
</ul>

Remember that HTML sitemaps are for human consumption, they are not meant for search engines. For that reason, Google Webmaster Tool and others don't even allow you to submit an HTML sitemap.

XML Sitemap #

XML Sitemap is the most preferred way of creating sitemaps today. Webmaster tools provided by major search engines accepts XML sitemap. Here is an example of XML sitemap:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://www.example.com/home</loc>
    <lastmod>2017-05-10</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.9</priority>
  </url>
  <url>
    <loc>http://www.example.com/blog/</loc>
    <lastmod>2017-05-10</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.6</priority>
  </url>
  <url>
    <loc>http://www.example.com/contact/</loc>
    <lastmod>2017-05-10</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.6</priority>
  </url>
</urlset>

Django provides a sitemap framework (django.contrib.sitemaps) which automates the process of creating sitemaps.

Installing Sitemap Framework #

To install sitemap framework add 'django.contrib.sitemaps' to the INSTALLED_APPS list in settings.py file. The sitemaps framework also depends on the sites framework (django.contrib.sites), which we have already installed in the previous lesson. At this point, INSTALLED_APPS setting should look like this:

djangobin/django_project/django_project/settings.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#...

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.humanize',
    'django.contrib.flatpages',
    'django.contrib.sites',
    'django.contrib.sitemaps',
    'djangobin',
]

#...

The sitemaps framework does not require any additional table. So you don't need to run the migrate command. We can verify this fact by running migrate command as follows:

$ ./manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, djangobin, flatpages, sessions, sites
Running migrations:
  No migrations to apply.

Notice the output "No migrations to apply.". This tells us that sitemap framework doesn't create any additional tables.

We are now ready to create sitemaps.

Creating Sitemap Class #

A sitemap class is just a Python class which inherits from django.contrib.sitemaps.Sitemap class. The sitemap class represents a section of the entries in the sitemap. For example, one sitemap class could represent all entries of the blog, while another sitemap class could represent all the flatpages and so on.

In our case, we want sitemap to contain links to all public snippets and flatpages. As a result, we will create two sitemap classes: SnippetfSitemap and FlatPageSitemap.

Create a new file named sitemaps.py in the djangobin app directory and add the following code to it.

djangobin/django_project/djangobin/sitemaps.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from django.contrib.sitemaps import Sitemap
from django.contrib.flatpages.models import FlatPage
from .models import Snippet


class SnippetSitemap(Sitemap):
    changefreq = 'monthly'
    priority = 0.9

    def items(self):
        return Snippet.objects.all()


class FlatPageSitemap(Sitemap):
    changefreq = 'monthly'
    priority = 0.9

    def items(self):
        return FlatPage.objects.all()

Here is how it works:

In lines 1-3, we import necessary classes and functions.

In lines 6-11, we define a sitemap class named SnippetSitemap.

In lines 7-8, we are setting changefreq and priority attributes. The changefreq and priority are optional class attributes which indicate how frequently the page changes and priority of the URLs in relation to other URLs respectively.

Other possible values for changefreq attribute are:

  • 'always'
  • 'hourly'
  • 'daily'
  • 'weekly'
  • 'monthly'
  • 'yearly'
  • 'never'

Similarly, priority attribute can only contain a value from 0.0 to 1.0.

The changefreq and priority class attributes corresponds to <changefreq> and <priority> XML elements. In other words, sitemap framework will use the data from changefreq and priority attribute to create <changefreq> and <priority> elements in the sitemap file.

Next, we define the items() method. The job of items() method is to return a list of objects whose URLs we want to have in the sitemap.

Note that items() method just returns a list of objects. It doesn't build the URLs itself. To build the URLs get_absolute_url() method of the Snippet model will be called implicitly.

The FlatPageSitemap class is defined in a similar way. The only difference is that here the items() method returns a list of FlatPage objects instead of Snippet objects.

Our sitemap class is ready. We just need to create a URL pattern for it.

The sitemap framework (django.contrib.sitemaps) provides a view called sitemap() which facilitates the creation of sitemap from Sitemap class. The sitemap() view accepts a required argument called sitemaps which is a dictionary object mapping to short section labels to its sitemap class.

Open djangobin's urls.py and modify it as follows:

djangobin/django_project/djangobin/urls.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#...
from django.contrib.flatpages import views as flat_views
from django.contrib.sitemaps.views import sitemap
from . import views
from .sitemaps import SnippetSitemap, FlatPageSitemap

# app_name = 'djangobin'

sitemaps = {
    'snippets': SnippetSitemap,
    'flatpages': FlatPageSitemap,
}

urlpatterns = [
                #...
    url(r'^about/$', flat_views.flatpage, {'url': '/about/'}, name='about'),
    url(r'^eula/$', flat_views.flatpage, {'url': '/eula/'}, name='eula'),
    url(r'^sitemap\.xml/$', sitemap, {'sitemaps': sitemaps}, name='sitemap'),
]

In lines 3 and 5, we import necessary classes.

In lines 9-12, we define a dictionary mapping short labels to sitemap class.

Finally, in 18, we define a new URL pattern named sitemap and pass sitemaps dictionary as a keyword argument.

Our Django project is ready to serve sitemaps. Open your browser and navigate to http://127.0.0.1:8000/sitemap.xml/. You should see a page like this:

Our sitemap is working as expected but notice that the host portion of URL contains example.com. This domain is coming from the Django sites framework (django.contrib.sites). To Change it, login to Django admin and then visit site list page ( http://127.0.0.1:8000/admin/sites/site/ ).

Click the domain name and you will be displayed Change Site form. In the form change Domain name and Display name to 127.0.0.1:8000 and click SAVE to update the changes.

Revisit sitemap page (http://127.0.0.1:8000/sitemap.xml/) again. At this point, your sitemap should be generating URLs using 127.0.0.1:8000 as host instead of example.com. You will need to update this setting once more at the time of deployment.