loading...
Cover image for How to add sitemap.xml to your Django Blog and make it work on Heroku (SEO)

How to add sitemap.xml to your Django Blog and make it work on Heroku (SEO)

radualexandrub profile image Radu-Alexandru B Updated on ・3 min read

Okay, I've spent a little to much time to figure this out, but here's my version of the Simplest Way to Add sitemap.xml to a Django App that is hosted on Heroku. This will also solve the error: "Internal Error 500" when trying to access /sitemap.xml from Heroku live app (production).

First things first, make sure you have what to serve as static or as dynamic links. In this example, I'll add to my sitemap.xml my dynamically created BlogPosts and 3 more static pages: Main/Index.html, About.html and Contact.html. So let's get started:

Firstly we need to add to our settings.py file the followings:

# settings.py
INSTALLED_APPS = [
    ...

    'django.contrib.sitemaps',
    'django.contrib.sites',
]
SITE_ID = 1
Enter fullscreen mode Exit fullscreen mode

Then, locally, we need to open our terminal and run python manage.py migrate. This will add to our local database the Sites model.
Sites table

We observe that the first entry in Sites table (with SITE_ID == 1) is "example.com"... We will later change that in production when we'll push to Heroku.

Now, we need to create a new file in our MainApp (Django App that we created at beginning of our project when we ran ./manage.py startapp MainApp), namely ../MainApp/sitemaps.py. Here we'll add the followings, we can also refer to the documentation on Django Sitemaps:

# sitemaps.py
from django.contrib.sitemaps import Sitemap
from django.shortcuts import reverse
from .models import BlogPost

class BlogPostSitemap(Sitemap):
    changefreq = "weekly"

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

class StaticViewSitemap(Sitemap):
    changefreq = 'monthly'

    def items(self):
        return ['index', 'about', 'contact']

    def location(self, item):
        return reverse(item)
Enter fullscreen mode Exit fullscreen mode

Now we need to add our continuingly generated sitemap.xml to our MainApp/urls.py. So we need to add these lines:

# urls.py
from django.contrib.sitemaps.views import sitemap
from .sitemaps import BlogPostSitemap, StaticViewSitemap

sitemaps = {
    'posts': BlogPostSitemap,
    'static': StaticViewSitemap,
}

urlpatterns = [
    ...
    path('sitemap.xml', sitemap, {'sitemaps': sitemaps}),
]
Enter fullscreen mode Exit fullscreen mode

Good. We can check that sitemap.xml is displayed in our local server by running python ./manage.py runserver and access our http://localhost:8000/sitemap.xml.

Aaand we are done! almost. Now we can finally push our code to Heroku, in the classic way:

> git status
> git add -A
> git commit -m "Add sitemap.xml to Django App"
> git push heroku master
Enter fullscreen mode Exit fullscreen mode

But here's the catch... Now when we are trying to access https://myappname.herokuapp.com/sitemap.xml we get an "INTERNAL SERVER ERROR (500)". Also, if we try to access our Sites model in our Admin page, we get the same error.

But why's that?

When we pushed our code to Heroku, our heroku server calls the "makemigrations" command from our manage.py, but we didn't manually created (wrote any code) to our models.py file, so makemigrations will return "No changes detected", therefore will not run "migrate" command.

So, we need to manually run migrate command from our heroku server. To do that, we simply call in our terminal these commands in our django project folder:

> heroku run bash
$ python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

And that's all. But now we also need to access again our admin page from our heroku deployed app, and change that first entry from Sites model from "example.com" to "myappname.herokuapp.com". Then, we'll have to run

> heroku restart
Enter fullscreen mode Exit fullscreen mode

And now we are really done. We can access our sitemap from myappname.herokuapp.com/sitemap.xml.

I hope this mini-tutorial will help someone one day. It will certain help me to not struggle again if I encounter again this problem.

Happy coding,

R.B.

Discussion

pic
Editor guide
Collapse
dumdum profile image
dum dum

Hi! I got problem with my sitemap.xml url.
In local localhost:8000/sitemap.xml works.
But in production domain.com/sitemap.xml got error http 500.
I'm using django3.1, python 3.8.5, heroku hobby basic.

Once I successfully submitted my sitemap on google search console.
But suddenly after few days when I tried to resubmit the sitemap, I got error "couldn't fetch".
When I checked heroku logs --tail, and try to visit domain.com/sitemap.xml, I got http error 500.
Site matching query does not exist.

I've set auto migrate on procfile, so automatically heroku will migrate for me everytime I deployed my app.
I've tried to manually migrate on heroku cli, then restart dyno using heroku restart. But error http 500 still exist.

I researched on the internet, tried many solutions, but didn't work.
Please help. Thanks

Collapse
radualexandrub profile image
Radu-Alexandru B Author

Hi,
Do you have any "Sites" model when you are accessing the admin panel from domain.com/admin (from deployment)? If not, you should open your terminal and call (after you added sitemap configurations as shown in this post):

> heroku run bash
$ python manage.py migrate
# CTRL+D
> heroku restart

This was my solution to fixing the problem that you have. However, if you do have a "Sites" model in your admin panel, try accessing it and change the first entry from example.com to yourdomain.com. Furthermore, check that you have the corresponding settings in YourDjangoApp/settings.py:

SECRET_KEY = os.environ.get('SECRET_KEY')
DEBUG = (os.environ.get("DEBUG_VALUE") == "True")
ALLOWED_HOSTS = ["yourdomain.com",
                 "https://yourdomain.com/",
]
INSTALLED_APPS = [
    ...
    'django.contrib.sitemaps',
    'django.contrib.sites',
]
SITE_ID = 1

Also, recheck your MainApp/urls.py as shown in this post's mini-tutorial.
Hope you will find a solution to your problem... Good luck!

Collapse
dumdum profile image
dum dum

I've checked everything, I did what you told me.
Still got error 500 in production. :(

Argh.. I spent months finding this solutions.
Also, I have another problem about environment variables in Windows.
I put my secret key in my environment variables, I set my settings.py, then I ran py manage.py runserver.

I got error "django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty."

I don't know what to do. :(