Do you want to add a favicon to your Django site the right way? Want to add it to your admin site as well? Read this guide to find out how!
What is a Favicon?
A favicon (a.k.a a “favorite icon” or a “shortcut icon”) is a small image that appears with the title of a web page in a browser. Typically, it’s a logo. Favicons were first introduced by Internet Explorer 5 in 1999, and they have since been standardized by W3C. Traditionally, a site’s favicon is saved as 16×16 pixel “favicon.ico” file in the site’s root directory, but many contemporary browsers support other sizes, formats, and locations. There are a plethora of free favicon generators available online. Every serious website should have a favicon.

The favicon for this blog is circled above in red.
Making the Favicon a Static File
Before embedding the favicon in web pages, it must be added to the Django project as a static file. Make sure the favicon is accessible however you choose to set up static files. The simplest approach would be to put the image file under a directory named static/images and use the standard static file settings. However, I strongly recommend reading the official docs on static files:
Embedding the Favicon into HTML
Adding the favicon to a Django web page is really no different than adding it to any other type of web page. Simply add the link for the favicon file to the HTML template file’s header using the static URL. It should look something like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!– The link tag within the head section adds the favicon to the page. –> | |
<!– Presume that the favicon is a static file accessible at the images/favicon path. –> | |
<!– Remember to "load static", too! –> | |
{% load static %} | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>My Page</title> | |
<link rel="shortcut icon" href="{% static 'images/favicon.ico' %}" /> | |
</head> | |
<body> | |
… | |
</body> | |
</html> |
Better Reuse with a Parent Template
Most sites use only one favicon for all pages. Rather than adding the same favicon explicitly to every page, it would be better to write a parent template that adds it automatically for all pages. A basic parent template could look like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!– This is a basic example of a Django parent template. –> | |
<!– It adds a favicon to the page. –> | |
<!– The title is set by overriding the "title" block. –> | |
<!– Body content is added by overriding the "content" block. –> | |
<!– Tweak this parent template to meet your project's needs. –> | |
{% load static %} | |
<html lang="en"> | |
{% block head %} | |
<head> | |
<meta charset="UTF-8"> | |
<title>{% block title %}{% endblock %}</title> | |
<link rel="shortcut icon" href="{% static 'images/favicon.ico' %}" /> | |
</head> | |
{% endblock %} | |
<body> | |
{% block content %} | |
{% endblock %} | |
</body> | |
</html> |
And a child of it could look like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!– This is an example of a Django child template. –> | |
<!– It extends: https://gist.github.com/d7f20ccd5620f64d761ec546fd9eb37a –> | |
<!– The parent template sets the favicon. –> | |
{% extends "django_example_parent.html" %} | |
{% block title %}My Page{% endblock %} | |
{% block content %} | |
<div> | |
… | |
</div> | |
{% endblock %} |
As good practice, other common things like CSS links could also be added to the parent template. Customize parent templates to your project’s needs.
Admin Site Favicon
While the admin site is not the main site most people will see, it is still nice to give it a favicon. The best way to set the favicon is to override admin templates, as explained in this StackOverflow post. This approach is like an extension of the previous one: a new template will be inserted between an existing parent-child inheritance to set the favicon. Create a new template at templates/admin/base_site.html with the contents below, and all admin site pages will have the favicon!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!– The path and name for this file should be "templates/admin/base_site.html". –> | |
<!– It overrides the original admin template and will be picked up by all of its children. –> | |
<!– This template override has been verified for Django 1.11 and 2.0. –> | |
{% extends "admin/base_site.html" %} | |
{% load static %} | |
{% block extrahead %} | |
<link rel="shortcut icon" href="{% static 'images/favicon.ico' %}" /> | |
{% endblock %} |
Make sure the template directory path is included in the TEMPLATES setting if it is outside of an app:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TEMPLATES = [ | |
{ | |
# … | |
'DIRS': [os.path.join(BASE_DIR, 'templates')], | |
# … | |
}, | |
] |
Django REST Framework Browsable API Favicon
The Django REST Framework is a great extension to Django for creating simple, standard, and seamless REST APIs for a site. It also provides a browsable API so that humans can easily see and use the endpoints. It’s fairly easy to change the browsable API’s favicon using a similar template override. Create a new template at templates/rest_framework/api.html with the following contents:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!– The path and name for this file should be "templates/rest_framework/api.html". –> | |
<!– It overrides the original browsable API template and will be picked up by all of its children. –> | |
<!– This template override has been verified for Django 2.0. –> | |
{% extends "rest_framework/base.html" %} | |
{% load static %} | |
{% block style %} | |
{{ block.super }} | |
<link rel="shortcut icon" href="{% static 'images/favicon.ico' %}" /> | |
{% endblock %} |
Favicon URL Redirect
A number of other articles (here, here, and here) suggest adding a URL redirect for the favicon file. Unfortunately, I got mixed results when I attempted this method myself: it worked on Mozilla Firefox and Microsoft Edge but not Google Chrome. (Yes, I tried clearing the cache and all that jazz.)
Django Favicon Apps
There are open-source Django apps for handling favicons more easily. I have not used them personally, but they are at least worth mentioning:
Just a ‘thank you’ comment, your solution works quite well for the site in itself, although for the admin (which is seldom used), I get some kind of ‘template loop’. Then again, my client is using a hopelessly outdated version of Django, so most workarounds that I could see on the web (and possibly your own instructions) are meant for more recent versions… unfortunately, this is one of those cases where updating is not an option!
In any case, what mattered most was having a favicon for the ‘main’ site, so that’s done! Thanks 🙂
LikeLike
Glad it helped!
LikeLike
Brilliant! Thanks for the help
LikeLike