Search code examples
static-filesdjango-1.8

Static files not working in Django development


I'm trying to follow the section in the Django docs called Managing static files. I am interested in finding out:

  1. What I am doing wrong.
  2. Or, what is wrong with the Django docs.

1) Make sure that django.contrib.staticfiles is included in your INSTALLED_APPS.

In the default settings.py file:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',  #<****HERE*****
)

2) In your settings file, define STATIC_URL, for example: STATIC_URL = '/static/'

In the default settings.py:

STATIC_URL = '/static/'

3) In your templates, either hardcode the url like /static/my_app/myexample.jpg

In mysite2/mysite2/views.py:

from django.http import HttpResponse

def index(request):
    return HttpResponse('''

        <h2>Hello</h2>
        <img src="/static/mysite2/Aerial03.jpg">


    ''')

4) Store your static files in a folder called static in your app. For example: my_app/static/my_app/myimage.jpg.

Here is my directory structure:

(django186p34)~/django_projects$ tree mysite2

mysite2
├── db.sqlite3
├── manage.py
└── mysite2
    ├── __init__.py

    ├── settings.py
    ├── static           #<****HERE*****
    │   └── mysite2
    │       └── Aerial03.jpg
    ├── urls.py
    ├── views.py
    └── wsgi.py

4 directories, 13 files

But after starting the server:

(django186p34)~/django_projects/mysite2$ python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).
November 26, 2015 - 02:44:57
Django version 1.8.6, using settings 'mysite2.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

And then navigating in my browser to:

http://localhost:8000/

I see the text:

Hello

but the image is not found:

[Error] Failed to load resource: the server responded with a status of 404 http://localhost:8000/static/mysite2/Aerial03.jpg

I've tried many combinations of urls in my html and nothing works.

Here is settings.py in its entirety(I made no changes):

"""
Django settings for mysite2 project.

Generated by 'django-admin startproject' using Django 1.8.6.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'pmaup3%)m09cs2goldduw2iogso%(#8cz0s-zmr%*e'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'mysite2.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'mysite2.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


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

STATIC_URL = '/static/'

Solution

  • This fixed things:

    INSTALLED_APPS = (
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'mysite2',  #<*****HERE*****
    )
    

    And if you organize things so that you have apps inside your project, e.g.:

    (django186p34)~/django_projects$ tree mysite3
    mysite3
    ├── db.sqlite3
    ├── manage.py
    ├── myapp
    │   ├── __init__.py
    
    │   ├── admin.py
    │   ├── migrations
    │   │   
    
    │   │    
    │   ├── models.py
    │   ├── static
    │   │   └── myapp
    │   │       └── Aerial03.jpg
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    └── mysite3
        ├── __init__.py
    
        ├── settings.py
        ├── urls.py
        └── wsgi.py
    
    8 directories, 24 files
    

    Then in settings.py add your app name to INSTALLED_APPS:

    INSTALLED_APPS = (
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'myapp',  #<*****HERE*****
    )
    

    Everything else in the default settings.py stays the same. However, the urls are different:

    mysite3/mysite3/urls.py:

    from django.conf.urls import include, url
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', include(admin.site.urls)),
    
        url(r'^myapp/', include('myapp.urls')),
    ]
    

    mysite3/myapp/urls.py:

    from django.conf.urls import url
    
    from . import views
    
    urlpatterns = [
        url(r'^$', views.index, name='index'),
    ]
    

    And in your browser, the url becomes:

    http://localhost:8000/myapp/
    

    myapp/views.py:

    from django.shortcuts import render
    
    # Create your views here.
    
    from django.http import HttpResponse
    
    
    def index(request):
        return HttpResponse('''
    
            <h2>Hello</h2>
            <img src="/static/myapp/Aerial03.jpg">
    
    
        ''')