How to create your own sitemap using a view with Django ?

Created September 27, 2022 | Viewed 265 | by Benjamin Edit


Example of how to create your own sitemap using a view with Django:

Note: Django comes with a high-level sitemap-generating framework to create sitemap XML files.see. However, I had to create my own sitemaps to deal with subdomains.

Create a sitemap

Lets consider for example a website with an ensemble of articles stored in the following model:

class Article(models.Model):
    url = models.CharField(max_length=1000, unique=True)
    title = models.CharField(max_length=1000)
    content = models.TextField()
    date_created = models.DateTimeField(default=datetime.now)
    date_modified = models.DateTimeField(default=datetime.now)
    language = models.CharField(max_length=4)
    removed = models.BooleanField(default=False)

example of url: /Articles/MyFirstArticle/.

To create a sitemap with all articles go to urls.py and add:

url(r'^Sitemaps/articles\.xml$', views.sitemap_article_view, name='sitemap_article_view'),

then create a view that render an xml file:

def sitemap_article_view(request):
    content = '''<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    '''
    article_obj_list =  Article.objects.filter(removed=False)
    for article_obj in article_obj_list:
        content += '''<url>
        <loc>{}</loc>
        <lastmod>{}</lastmod>
        <changefreq>yearly</changefreq>
        <priority>1.0</priority>
    </url>'''.format(article_obj.url, datetime.date.strftime(article_obj.date_modified, "%Y-%m-%d"))
    content += ''' </urlset>'''
    return HttpResponse(content, content_type='text/xml')

Another example

Create two sitemaps for two subdomains:

www.mysite.com
fr.mysite.com

Sitemaps

def sitemap_article_view(request):
    full_url = request.build_absolute_uri()
    language = 'en'
    if '127.0.0.1' in full_url:
        url_prefix = 'http://127.0.0.1:8000'
    else:
        full_url_splited =  full_url.split('/')
        scheme = full_url_splited[0]
        url_prefix = '{}//{}'.format(scheme,full_url_splited[2] )
        if 'www' not in full_url:
            subdomain = full_url_splited[2].split('.')[0]
            language = subdomain
    content = '''<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    '''
    article_list_obj =  Article.objects.filter(note_type='article',language=language,removed=False,public=True)
    for article_obj in article_list_obj:
        content += '''<url>
        <loc>{}{}</loc>
        <lastmod>{}</lastmod>
        <changefreq>yearly</changefreq>
        <priority>1.0</priority>
    </url>'''.format(url_prefix,article_obj.url,datetime.date.strftime(article_obj.date_modified, "%Y-%m-%d"))
    content += ''' </urlset>'''
    return HttpResponse(content, content_type='text/xml')

References