Now Hiring: Are you a driven and motivated 1st Line IT Support Engineer?

Nov. 30, 2020

Adding Sitemaps to your Django Projects without getting Server Error (500)

Along with a host of advantages, a sitemap is a fundamental feature of your website’s search engine optimization (SEO) strategy. Assisting search engines in navigating a website, sitemaps are a good way of letting search engines know that your website is available and can be crawled by them.

So, whether you're building a website from scratch or planning an overhaul, a sitemap is essential.

From technical point of view a sitemap is an XML file on your website that tells search-engine indexers how frequently your pages change and how “important” certain pages are in relation to other pages on your site. This information helps search engines index your site.

The Django sitemap framework automates the creation of this XML file by letting you express this information in Python code.

Now let's go step by step to implement sitemap framework together:


1. Installation of framework

Open settings.py of your Django project. 

# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'django.contrib.sitemaps',
]

SITE_ID = 1

Add 'django.contrib.sitemaps' and 'django.contrib.sites' to your INSTALLED_APPS setting.

Also set  SITE_ID = 1 which select a domain name from Sites on Admin page and initially this refers to "example.com". We will change this later on to our domain name while in production.


TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ["beakwise/templates/"],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

Make sure your TEMPLATES setting contains a DjangoTemplates backend whose APP_DIRS options is set to True.


2. Creating Static and Dynamic Sitemaps

Now in your main application folder (where the settings.py is placed) create a new python file called sitemaps.py and copy-paste the following codes there.

from django.contrib.sitemaps import Sitemap
from django.shortcuts import reverse

from blog.models import Post


class PostSitemap(Sitemap):
changefreq =
"weekly"
priority = 0.9

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

def lastmod(self, obj):
return obj.updated_on


class StaticViewSitemap(Sitemap):
changefreq =
'monthly'

def items(self):
return ['index','training','aboutus','privacy']

def location(self, item):
return reverse(item)

StaticViewSitemap generally holds the URLs which is not changing frequently and you can point at all of them in items list. I've added just a couple of samples.

If you have dynamic contents like blog posts, career job postings etc., you can create a Sitemaps for each of them. At the end they will merge into sitemap.xml file. In this example you can see the definition to create a sitemap for every posts on your blog.

  • changefreq and priority are class attributes corresponding to <changefreq> and <priority> elements, respectively. They can be made callable as functions, as lastmod was in the example.
  • items() is a method that returns a sequence or QuerySet of objects. The objects returned will get passed to any callable methods corresponding to a sitemap property (location, lastmod, changefreq, and priority).
  • lastmod should return a datetime.


3. Let's Activate the Sitemap Generation

To activate sitemap generation on your Django site, add the following lines to your urls.py of main application where you can find also settings.py file.

from django.contrib.sitemaps.views import sitemap
from .sitemaps import PostSitemap, StaticViewSitemap, CareerSitemap

sitemaps = {

'posts': PostSitemap,
'static': StaticViewSitemap,
}


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

 
4. Be sure to implement
 get_absolute_url()method

For models based on dynamic sitemaps you have to define get_absolute_url(). In this example the model is a Post model so let's add that method to the model definition.

class Post(models.Model):
...
slug = models.SlugField(max_length=255, unique=True)
updated_on = models.DateTimeField(auto_now=True)

def get_absolute_url(self):
return reverse('blog:blog_detail', args=[self.slug])

If you want a meaningful sitemap for each of the postings, means searchable ones, better to use auto generated and unique slug field for that purpose.   

Now there is one reason here that you may get "Server Error (500)" in production environment. You are getting this error if creation of sitemap fails for some reasons. You can anytime check what is the problem by looking at gunicorn.log file.

In my case although sitemap.xml is created in DEBUG=True localhost environment without a problem I've got an error of 500 on production. 

The problem was the definition of location of URL which was "blog:blog_detail". The first one is namespace of application. But if your application urls.py file don't include that definition sitemap creation failed and you end up with a Server Error in DEBUG=False environments.

So I've put the following line to urls.py and the problem was solved.

from django.urls import path
from . import views

app_name =
"blog" <= Added this line

urlpatterns = [
path(
"", views.blog_index, name="blog_index"),
path("detail/<slug:slug>/", views.blog_detail, name="blog_detail"),
path("category/<category>/", views.blog_category, name="blog_category"),
]

As a habit better to declare the namespace all the time and define url mapping with namespaces not to get any kind of error in the future.


5. Migrate to Use Sites Framework

Since we are using Sites frameworks don't forget to run  python manage.py migrate 

In admin panel you will than see the Sites admin which only includes example.com as an initial domain site.



6. First try in localhost environment

Just type the following to browser http://localhost:8000/sitemap.xml than you will see the xml created. Make your deployments to production. 


7. example.com to your domain name on production

Now change example.com with the name of your domain. In my case it is beakwise.com and after changing domain name in Admin panel I've tried this one https://beakwise.com/sitemap.xml  and here is the created site map. 


That's all for sitemaps.

Stay healthy !






0 Comments
Leave a Comment