How to add favicon to Django in 4 steps

Favicons in Django
Image: Favicons in Django (License: CC-BY-SA Marcelo Canina)

Two methods to add favicons to a website

Published: Tag Adsense

Overview

Favicon stands for favourite icon and it is an “icon representing the page or site, and should be used by the user agent when representing the page in the user interface”1.

Every website should have an icon associated, most browsers expects to find a favicon.ico at you website’s root directory, but in Django we will have our static files typically in a sub-directory or subdomain.

In this guide we will set up Django to serve favicons at root so you won’t see this kind of error in your logs anymore:

186.116.000.18 - - [01/Sep/2020:22:53:02 +0000] "GET /favicon.ico/ HTTP/1.1" 404 4536 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36

First of all, why this happens? favicon.ico is the file by which for historical reasons browsers look for when trying to get an icon for your your website.

In the absence of a link with the icon keyword, for Document objects obtained over HTTP or HTTPS, user agents may instead run these steps in parallel:

Let request be a new request whose URL is the absolute URL obtained by resolving the URL "/favicon.ico" against the document’s URL, client is the Document object’s Window object’s environment settings object, type is "image", destination is "subresource", synchronous flag is set, credentials mode is "include", and whose use-URL-credentials flag is set.

Here we explore three alternatives to serve this file correctly.

  1. With a redirect or
  2. Serve directly from nginx

1. Create a favicon

Create a favicon online with a favicon generator.

2. Add to static folder

To serve static files we use Django’s staticsapp.

Put the favicon.ico in your static folder, typically it would be /static, you can check the value of the settings.STATIC_ROOT variable2 to be sure.

3. Serve

3.1 Redirect method

Your static files will be served using the path specified at STATIC_URL, for example, in your app/settings.py you would have something like:

STATIC_URL = "/static/"

This is the URL to use when referring to static files located in STATIC_ROOT (after running collectstatic). The problem with this is that most browsers would still expect to find a favicon.ico at the root of your website if you don’t explicitly specify it, https://example.com/favicon.ico and not at https://example.com/static/favicon.ico.

To address this we do a redirect RedirectView.as_view(url=staticfiles_storage.url("favicon.ico")) each time there is a request to /favicon.ico, in app/urls.py:

"""equilang URL Configuration
"""
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import include, path
from django.views.generic.base import RedirectView
from django.conf import settings

urlpatterns = [
	//...
    path(
        "favicon.ico",
        RedirectView.as_view(url=staticfiles_storage.url("favicon.ico")),
    ),
] 

The above import django.contrib.staticfiles.storage.url, is used to select the right storage backend, based in settings.STATICFILES_STORAGE variable’s value.

It also uses the Generic Class Based View django.views.generic.base.RedirectView to redirect to the specified URL.

3.2 Nginx method

3.2.1 Configure nginx

Using the location directive, which sets configuration depending on a request URI, we define an alias directive to serve the favicon.ico file.

In your nginx website virtual host configuration:

location /favicon.ico {
    alias /staticfiles/favicon.ico;
} 

4. Add to HTML

Lastly, we add the favicon to the head section of our base template:

{% load static %}

<link rel="icon"
 href="{% static 'favicon.ico' %}">

Check

No more favicon errors:


$ curl -I http://localhost:8000/favicon.ico
HTTP/1.1 302 Found
Date: Thu, 03 Sep 2020 14:36:15 GMT
Server: WSGIServer/0.2 CPython/3.6.8
Content-Type: text/html; charset=utf-8
Location: /static/favicon.ico
X-Frame-Options: DENY
Content-Length: 0
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
$ curl -I http://localhost:8000/static/favicon.ico
HTTP/1.1 200 OK
Date: Thu, 03 Sep 2020 14:36:26 GMT
Server: WSGIServer/0.2 CPython/3.6.8
Content-Type: image/vnd.microsoft.icon
Content-Length: 1150
Content-Disposition: inline; filename="favicon.ico"
Last-Modified: Mon, 16 Jul 2012 18:51:08 GMT

Conclucion

Now we will have the favicon defined both in our HTML and the typically /favicon.ico to be sure it is always served the right way.

References


  1. https://www.w3.org/TR/html53/links.html#link-type-icon ↩︎

  2. https://docs.djangoproject.com/en/3.1/ref/settings/#std:setting-STATIC_ROOT ↩︎

Uruguay
Marcelo Canina
I'm Marcelo Canina, a developer from Uruguay. I build websites and web-based applications from the ground up and share what I learn here.
comments powered by Disqus


Description of two simple methods to add a favicon.ico to a website's root location.

Clutter-free software concepts.
Translations English Español

Except as otherwise noted, the content of this page is licensed under CC BY-NC-ND 4.0 . Terms and Policy.

Powered by SimpleIT Hugo Theme

·