Search code examples
pythondjangopython-3.xdjango-settings

How can I get static files to work in my Django project?


Using: Python 3.7 and Django 2.1.4

I'm working through the tutorials in William S. Vincent's Django for Beginners book. I'm in the "Blog App" part of the book, and I've been following his instructions to the letter. However, I cannot seem to get the dev server to serve my static CSS file, no matter what I do.

My source code can be found here.

I'm using manage.py runserver to run a development demo server for local testing.

Here's my directory tree:

./
├── blog
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── blog_project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── db.sqlite3
├── manage.py
├── Pipfile
├── Pipfile.lock
├── static
│   └── css
│       └── base.css
└── templates
    ├── base.html
    └── home.html

Originally I updated my blog_project/settings.py with this line:

STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

and I put {% load static %} at the top of my templates/base.html file, as well as adding <link href="{% static 'css/base.css' %}" rel="stylesheet"> in the <head> ... </head> section.

After writing the static/css/base.css file, this should have worked. But it didn't. I researched the forums and Stack Overflow, and saw people advising adding the static directories to the blog_project/settings.py file, so I updated that file, adding the following to the bottom:

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICTILES_DIRS = [
    STATIC_ROOT,
]

Then I updated the blog_project/urls.py file, adding two new imports:

from django.conf.urls.static import static
from django.conf import settings

and the following line:

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

But even this didn't work.

You can check my settings.py, urls.py and base.html files to see what I'm talking about.

I expected the manage.py runserver to host the static files, but it did not. When I tried to load the CSS file directly, I got a 404 error.


Solution

  • First off, you misspelled your STATICFILES_DIRS in the linked settings.py file with a rampant T instead of an F: STATICTILES_DIRS.

    Second, do not put your STATIC_ROOT anywhere within your STATICFILES_DIRS. From the docs:

    Warning

    This (STATIC_ROOT) should be an initially empty destination directory for collecting your static files from their permanent locations into one directory for ease of deployment; it is not a place to store your static files permanently. You should do that (by that they mean 'store your static files') in directories that will be found by staticfiles’s finders, which by default, are 'static/' app sub-directories and any directories you include in STATICFILES_DIRS).

    Note: cursive text was added by me.


    So I recommend the following configuration for your setttings.py:

    STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'static'),
    )
    

    As long as you are in debugging mode, DEBUG=True, you should be good to go. There is also no need to add the STATIC_ROOT to the urlpatterns as you did in your urls.py. You only want to do that if you don't have django.contrib.staticfiles in your INSTALLED_APPS (see here).

    At the moment you want to switch to production, have a look at how this is done correctly.

    Hope that helped and happy coding!