Django Rest Framework – Missing Static Directory

Each Answer to this Q is separated by one/two green lines.

I have recently started a Digital Ocean server with a pre-installed Django image on Ubuntu 14.04. I wanted to create an API, and have decided on the Django Rest Framework. I installed the Django Rest Framework exactly according to http://www.django-rest-framework.org/.

Here is what the tutorial site looks like when I access it on my server.

enter image description here

As you can see, it does not look like the site on the rest framework tutorial website. This is because of the fact that when I view the source code of my site, all of the /static/rest_framework/* files give me a 404 error.

Here is my settings.py file in the Django ‘django_project’ root directory.

"""
Django settings for django_project project.

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

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

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


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

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '7Vnib8zBUEV3LfacGKi2rT185N36A8svyq8azJLvNpv7BxxzMK'

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

TEMPLATE_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',
    'rest_framework',
)

REST_FRAMEWORK = {
    # Use hyperlinked styles by default.
    # Only used if the `serializer_class` attribute is not set on a view.
    'DEFAULT_MODEL_SERIALIZER_CLASS':
        'rest_framework.serializers.HyperlinkedModelSerializer',

    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}

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

ROOT_URLCONF = 'django_project.urls'

WSGI_APPLICATION = 'django_project.wsgi.application'


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

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'django',
        'USER': 'django',
        'PASSWORD': 'yj4SM6qcP0',
        'HOST': 'localhost',
        'PORT': '',
    }
}

# Internationalization
# https://docs.djangoproject.com/en/1.6/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.6/howto/static-files/

STATIC_URL = '/static/'

Can anyone help me fix this missing /static/rest_framework/ location error? If I am going to have an API for my application I would like it to be a good looking one.

Let me know if you need anything else to help you fix this, and thank you in advance for your help.

I have found the solution to my problem!

After much mind boggling research, I re-read this stack overflow question that didn’t seem to help me the last time I took a look at it.

My new settings.py in my django_project folder now looks like this.

"""
Django settings for django_project project.

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

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

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


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

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'DwGCDqtcqzzGO2XK87u7bVSEUqHogZRFl4UdhkcCudSHxLUVvx'

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

TEMPLATE_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',
    'rest_framework',
)

REST_FRAMEWORK = {
    # Use hyperlinked styles by default.
    # Only used if the `serializer_class` attribute is not set on a view.
    'DEFAULT_MODEL_SERIALIZER_CLASS':
        'rest_framework.serializers.HyperlinkedModelSerializer',

    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}

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

ROOT_URLCONF = 'django_project.urls'

WSGI_APPLICATION = 'django_project.wsgi.application'


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

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'django',
        'USER': 'django',
        'PASSWORD': 'mpOQzpYFci',
        'HOST': 'localhost',
        'PORT': '',
    }
}

# Internationalization
# https://docs.djangoproject.com/en/1.6/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.6/howto/static-files/

STATIC_ROOT = '/home/django/django_project/django_project/static'
STATIC_URL = '/static/'

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

I now have a folder named ‘static’ right next to my settings.py file in my django_project folder with all necessary resources such as ‘rest_framework’ and ‘admin’. I restarted gunicorn after this change and reloaded my web page and it worked!

Thanks to those of you who tried to help, you did lead me in the right direction and probably made this go by a lot faster.

First, You need to set static url and static root in django settings.py

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static") 

Then collect all static files

python manage.py collectstatic

In my case I was relying on Gunicorn to run the server.
I tried updating my settings.py file by following the above threads but unfortunately nothing seemed to work for me.

In the end I scratched my head around DRF docs specially this part https://docs.djangoproject.com/en/dev/howto/static-files/

I managed to solve this problem by updating by urls.py as following.

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls), 
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Then updating my settings.py as follows.

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

And now execute => python manage.py collectstatic

I did this tens of times and I was going insane over it. I had DEBUG = False.

If you’re using Heroku to serve your website, try this link. It worked for me.
https://devcenter.heroku.com/articles/django-assets

In Summary:

  1. Make a static folder if you don’t have one already. (put it on the same level as your manage.py file)
  2. Add the Python package to the folder (Copy this folder into the static folder –> C:\Python37_64\Lib\site-packages\rest_framework)
  3. Add the code below to your project.

settings.py

...

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

...

MIDDLEWARE_CLASSES = (
# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
'whitenoise.middleware.WhiteNoiseMiddleware',

...

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'

# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)

# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

requirements.txt

...
#add whotrnoise to requirements
whitenoise

I was unable to get any of the above solutions to work on our webapp, but discovered that if the app can connect to an S3 bucket where it can access deployed static files, django rest_framework works pretty seemlessly (as discussed here). Here’s the relevant code for our settings.py:

    aws = pcfenv.get_service(label="aws-s3") # or however you are accessing your s3 bucket & credentials

    if aws is not None:
        keys = aws.credentials
        AWS_ACCESS_KEY_ID = keys["access_key_id"]
        AWS_SECRET_ACCESS_KEY = keys["secret_access_key"]
        AWS_STORAGE_BUCKET_NAME = keys["bucket"]
        AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
        AWS_S3_OBJECT_PARAMETERS = {
            'CacheControl': 'max-age=86400',
        }
        AWS_LOCATION = 'static'
        STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
        STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
        DEFAULT_FILE_STORAGE = 'mysite.storage_backends.MediaStorage'

    # static files
    STATIC_URL = '/static/'
    STATIC_ROOT = 'static/'

    # local storage
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '/media/uploads/'

You’ll need to pip install the boto3 and django-storages dependencies for it all to work.

you need both:

REST_FRAMEWORK = {
    # Use hyperlinked styles by default.
    # Only used if the `serializer_class` attribute is not set on a view.
    'DEFAULT_MODEL_SERIALIZER_CLASS':
        'rest_framework.serializers.HyperlinkedModelSerializer',

    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
} 

and

the

python manage.py collectstatic

with the relevant directories set up.

the latter without the former won’t do the work.

In debug mode, no changes are required.

If you are in a production environment, you need to set the static files point, usually set in nginx

location /static {
    alias /<your app>/static; # your Django project's static files - amend as required
}


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .