Django Favicon Setup (including Admin)

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.

AP 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:


<!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:


<!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 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!


<!– 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:


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:


<!– 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:

4 comments

  1. 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 🙂

    Like

Leave a comment