Add Sitemap to Your Django Site
Tags: beginners, codenewbie, django, python
Published: 2021-02-23 01:37:16

**you can jump to step 4 if you want to test it with your existing project**

<h1>Index</h1>
1- [Intorduction](#introduction)
2- [Environment Setup](#environment)
3- [Project Setup](#project)
4- [Add Sitemap](#sitemap)


##Introduction <a name="introduction"></a>
A sitemap tells search engines which pages and files you think are important in your site and also provides valuable information about these files.
it helps search engines to crawl your website quickly.


##Environment Setup<a name="environment"></a>
* create your virtual environment or use an existing one: `python -m venv env`
* activate your virtual environment `source env/bin/activate`
* install Django `pip install django`


##Project Setup <a name="project"></a>
* create new folder `mkdir django-add-sitemap && cd django-add-sitemap`
* create new project `django-admin startproject config .`
* create new app `python manage.py startapp blog` and add it to `INSTALLED_APPS`
* edit `blog/models.py` and paste these code in it:
```
from django.db import models
from django.urls import reverse

class Post(models.Model):
    STATUS_CHOICES = [('published', 'Published'), ('draft', 'Draft')]
    title = models.CharField(max_length=250)
    content = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=12, choices=STATUS_CHOICES, default='draft')

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('post-detail', kwargs={'slug': self.slug})

@receiver(post_save, sender=Post)
def save_slug(sender, instance=None, created=False, **kwargs):
    if created:
        instance.slug = slugify(instance.title)
        instance.save()
```
* run `python manage.py makemigrations` then `python manage.py migrate` and don't forget to create a superuser `python manage.py createsuperuser`
* add Post to `admin.py` and add some data for testing later.

# Add Sitemap <a name="sitemap"></a>
* first add `django.contrib.sitemaps` to `INSTALLED_APPS`
* create `blog/sitemaps.py` then paste this code to it:
```
from django.contrib import sitemaps
from .models import Post


class PostSitemap(sitemaps.Sitemap):
    changefreq = "weakly"
    priority = 0.8

    def items(self):
        return Post.objects.filter(status='published')
    
    def lastmod(self, obj):
        return obj.updated
```
`changefreq` this attribute is used to tell how frequently your site is changing. other values are `["always", "hourly", "daily", "monthly", "yearly", "never"]`.
you can override default `location` method if have you don't have `get_absolute_url` in your model.
* finally, map the URL for the sitemaps in the `config/urls.py` or `blog/urls.py` file.
```
# config/urls.py
from django.contrib.sitemaps.views import sitemap
from blog.sitemaps import PostSitemap

sitemaps = {
    "posts": PostSitemap,
}

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

here is how it looks like in a browser:
![Result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ztxnswfv12oa4y0bbfg.jpg)

source code is upload to github: https://github.com/abdulshak1999/Python/tree/main/django/website_sitemap

for more information check this: https://docs.djangoproject.com/en/3.0/ref/contrib/sitemaps/