Django Favicon Tutorial
Tags: django, python, tutorial, beginners
Published: 2020-03-13 12:12:51

This tutorial explains how to add a favicon to a Django website. The trick is it requires configuring your `static` files properly.

To start things off, create a local directory for your code. This can exist anywhere easily accessible but if you're on a Mac (as I am) the `Desktop` is a convenient choice. Navigate there from the command line and create a new directory called `favicon`, then change into it.

```
$ cd ~/Desktop
$ mkdir favicon && cd favicon
```

Now install Django with Pipenv and start the virtual environment with the `shell` command. (If you need help installing it [see here](https://djangoforbeginners.com/initial-setup/)). You'll know it works correctly because the directory name will be parentheses `(favicon)`.

```
$ pipenv install django==3.0.4
$ pipenv shell
(favicon) $
```

Ok, so far so good. Next create a new Django project with the `startproject` command called `favicon_project`. Include a period `.` at the end of the command so that a duplicate directory isn't created by Django.

```
(favicon) $ django-admin startproject favicon_project .
(favicon) $ python manage.py migrate
(favicon) $ python manage.py runserver
```

Go to [http://127.0.0.1:8000/](http://127.0.0.1:8000/) and see the Django Welcome page.

![Django welcome page](https://dev-to-uploads.s3.amazonaws.com/i/mg3r9mhg8pnrdi5e7ugk.png)

## Pages app  

Now we'll add a basic homepage. This requires a dedicated app we'll call `pages`. Stop the local server with the `Control+c` command.

```
(favicon) $ python manage.py startapp pages
```

Add it to the bottom of the `INSTALLED_APPS` configuration within `favicon_project/settings.py` to notify Django of it.

```python
# favicon_project/settings.py
INSTALLED_APPS = [
    ...
    'pages.apps.PagesConfig', # new
]
```

We need a URL, a view, and a template for the homepage. While the actual order here is optional--you'll need all three--I prefer to start with URLs.

## URLs

This means adding our `pages` app to the top-level `favicon_project/urls.py` file and setting a URL path for it. We don't want any URL changes so we'll use the empty string `''` for this. Also note that we must import `include` on the second line as well.

```python
# favicon_project/urls.py
from django.contrib import admin
from django.urls import path, include # new

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('pages.urls')), # new
]
```

For some reason Django's `startapp` command does not generate a `urls.py` file for us even though we almost need one. So create one now within `pages`.

```
(favicon) $ touch pages/urls.py
```

And then populate it as follows, referencing a `HomePageView` we will create in the next step.

```python
# pages/urls.py
from django.urls import path

from .views import HomePageView

urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
]
```

## Views

Now we're on to the view which we know will be called `HomePageView` and can rely on Django's built-in [TemplateView](https://docs.djangoproject.com/en/dev/ref/class-based-views/base/#django.views.generic.base.TemplateView). Note that it references a template called `home.html` that we've yet to create.

```python
# pages/views.py
from django.views.generic import TemplateView

class HomePageView(TemplateView):
    template_name = 'home.html'
```

## Templates

And finally our template. We could place this within `pages` by creating a `pages/templates/pages/` directory structure but I prefer creating a top-level `templates` directory instead. Let's do that now and add our `home.html` template.

```
(favicon) $ mkdir templates
(favicon) $ touch templates/home.html
```

Now we must tell Django to look here *as well* as in the app-level `templates` directory. We do that by updating the `DIRS` configuration within our `settings.py` file.

```python
# favicon_project/settings.py
TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # new
        ...
    }
]
```

The template itself can just say "Homepage" for now.

```html
<!-- templates/home.html -->
<h1>Homepage</h1>
```

All set. Make sure the server is running.

```
(favicon) $ python manage.py runserver
```

Then check out our new homepage at [http://127.0.0.1:8000/](http://127.0.0.1:8000/).

![Home Page](https://dev-to-uploads.s3.amazonaws.com/i/517obb80rn7fxwlcnt38.png)

## Static Files  

How to add a favicon now? We must set up static files where it will live.

Django relies on the [staticfiles app](https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/) to manage static files from across our entire project. The `startproject` command already comes with a [STATIC_URL](https://docs.djangoproject.com/en/dev/ref/settings/#static-url) configuration, which sets the URL we use to reference static files.

We'll need to set up [STATICFILES_DIRS](https://docs.djangoproject.com/en/dev/ref/settings/#staticfiles-dirs) which defines the location of static files in *local development*. In our project these will all live within a top-level `static` directory.

```python
# favicon_project/settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),] # new
```

Create a local `static` folder for our favicon stopping the local server `Control+c` if necessary.

```
(favicon) $ mkdir static
```

## Favicon
There are any number of favicon generators available online. If you want one to use in this project, you can [download it here](https://learndjango.com/static/images/tutorials/favicon/favicon.ico).

Move this file into your project within the `static` directory so it should be `static/favicon.ico`.

For the final step, update our template so that we include `load static` at the top and then add an `href` for our `favicon.ico` file.

```html
<!-- templates/home.html -->
{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <title>Django Favicon Tutorial</title>
    <link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
  </head>
  <body>
    <h1>Homepage</h1>
  </body>
</html>
```

Start up the server again with `python manage.py runserver` and refresh the page at [http://127.0.0.1:8000/](http://127.0.0.1:8000/).

![Favicon](https://dev-to-uploads.s3.amazonaws.com/i/dtxkahxmd6m0xbxfs9q0.png)

Boom! There's our favicon.