Managing (Deploying) Static files (CSS, Images, Javascript) on Shared Host
This chapter describes how we can use "static files" in production.
Django for my shared account with justhost.com has the following setup:
- The project location is /home/myusername/myproject, more specifically, /home2/boogtob1/djangoproject.
- ~/public_html/dj/ directory has following files or folders:
$ pwd /home2/bogotob1/www/dj $ ls ./ ../ djangoproject.fcgi* .htaccess static/
- The static files is stored in ~/public_html/dj/static/djangoapp/ where the home(~) is /home2/boogtob1/.
- So, the urls for requests look like this: bogotobogo.com/dj/ for my simple djangoapp and bogotobogo.com/dj/admin for admin page.
Initially (without the static setting), all of my static files were not served properly. In other words, css, images, and js were not rendered properly for all my Django apps including admin pages. Note that when I used them hard coded, it worked. For example, my djangoapp/templates/base.html:
<html> <head> <title>This is Hello World app!</title> <link rel="stylesheet" type="text/css" href="/dj/static/djangoapp/mystyle.css"/> </head> <body> <img src="/dj/static/djangoapp/DjangoImg.png" alt="My image"/> <h1>Welcome to Django at bogotobogo.com (djangoapp/templates/base.html)</h1> {% block content %} {% endblock %} </body> </html>
However, when I used the static template tag as shown below, it did not work:
<html> <head> <title>This is Hello World app!</title> {% load staticfiles %} <link rel="stylesheet" type="text/css" href="{% static "djangoapp/mystyle.css" %}" /> </head> <body> {% load staticfiles %} <img src="{% static "djangoapp/DjangoImg.png" %}" alt="My image"/> <h1>Welcome to Django at bogotobogo.com (djangoapp/templates/base.html)</h1> {% block content %} {% endblock %} </body> </html>
So, I need the setup described in the sections below to make the static template tag to work.
Websites generally need to serve additional files such as images, JavaScript, or CSS which are referred as "static files". Django provides django.contrib.staticfiles to help us manage them.
This section describes how we can serve these static files in production.
- We should make sure that django.contrib.staticfiles is included in our INSTALLED_APPS.
# Application definition INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'djangoapp', 'taggit', 'blog', 'forum', 'todo', )
When we deploy the static files, django.contrib.staticfiles provides a convenience management command for gathering static files in a single directory so we can serve them easily. - In our settings file, we need to define STATIC_URL, for example:
STATIC_URL = '/dj/static/'
-
In our templates (base.html), either hardcode the url like /static/djangoapp/mystyle.css or, preferably, use the static template tag to build the URL for the given relative path by using the configured STATICFILES_STORAGE storage (this makes it much easier when we want to switch to a content delivery network (CDN) for serving static files).
<html> <head> <title>This is Hello World app!</title> {% load staticfiles %} <link rel="stylesheet" type="text/css" href="{% static "djangoapp/mystyle.css" %}" /> <!-- hard coded : working <link rel="stylesheet" type="text/css" href="/dj/static/djangoapp/mystyle.css"/> --> </head> <!--<body style="background-color:yellow;"> --> <body> {% load staticfiles %} <img src="{% static "djangoapp/DjangoImg.png" %}" alt="My image"/> <!-- hard coded : working <img src="/dj/static/djangoapp/DjangoImg.png" alt="My image"/> --> <h1>Welcome to Django at bogotobogo.com - (djangoapp/templates/base.html)</h1> {% block content %} {% endblock %} </body> </html>
-
We need to store our static files in a folder called static in our app. For example djangoapp/static/djangoapp/mystyle.css
body {background-color:yellow;} p {color:blue;}
- Set the STATIC_ROOT to the directory from which we like to serve these files. So, when we do collectstatic, it will copy all files from our static folders into the STATIC_ROOT directory. In my case, it is:
STATIC_ROOT = "/home2/bogotob1/www/dj/static/"
- Run the collectstatic management command:
$ pwd /home2/bogotob1/djangoproject $ python manage.py collectstatic You have requested to collect static files at the destination location as specified in your settings: /home2/bogotob1/www/dj/static This will overwrite existing files! Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: yes Copying '/home2/bogotob1/python/lib/python2.7/site-packages/django/contrib/admin/static/admin/css/login.css' Copying '/home2/bogotob1/python/lib/python2.7/site-packages/django/contrib/admin/static/admin/css/forms.css' Copying '/home2/bogotob1/python/lib/python2.7/site-packages/django/contrib/admin/static/admin/css/rtl.css' ... Copying '/home2/bogotob1/djangoproject/djangoapp/static/djangoapp/DjangoImg.png' Copying '/home2/bogotob1/djangoproject/djangoapp/static/djangoapp/mystyle.css'
As we can see, it copies all files from our static folders into the STATIC_ROOT directory.$ pwd /home2/bogotob1/www/dj/static $ ls ./ ../ admin/ djangoapp/ $ cd admin $ ls ./ ../ css/ img/ js/
$ cd ../djangoapp $ pwd /home2/bogotob1/www/dj/static/djangoapp $ ls ./ ../ DjangoImg.png mystyle.css
As usual, we need the following two files for shared hosting environment:
~/www/dj/djangoproject.fcgi:
#! /home2/bogotob1/python/bin/python import sys, os sys.path.insert(0, "/home2/bogotob1/python") sys.path.insert(13, "/home2/bogotob1/djangoproject") sys.path.append("/home2/bogotob1/python/lib/python2.7/site-packages/") os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoproject.settings' from django.core.servers.fastcgi import runfastcgi runfastcgi(method="threaded", daemonize="false")
where /home2/bogotob1/ is my home(~) directory.
~/www/dj/.htaccess:
# django AddHandler fcgid-script .fcgi RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f #RewriteCond %{REQUEST_URI} !^/static/ RewriteRule ^(.*)$ djangoproject.fcgi/$1 [QSA,L]
Here is the picture after rendering the css and image for my simple app, djangoapp:
The page source looks like this:
<html> <head> <title>This is Hello World app!</title> <link rel="stylesheet" type="text/css" href="/dj/static/djangoapp/mystyle.css" /> <!-- hard coded : working <link rel="stylesheet" type="text/css" href="/dj/static/djangoapp/mystyle.css"/> --> </head> <!--<body style="background-color:green;"> --> <body> <img src="/dj/static/djangoapp/DjangoImg.png" alt="My image"/> <!-- hard coded : working <img src="/dj/static/djangoapp/DjangoImg.png" alt="My image"/> --> <h1>Welcome to Django at bogotobogo.com - (djangoapp/templates/base.html)</h1> Django Template Inheritance Hello World - Django from djangoapp/views.py </body> </html>
Note that the new source is exactly the same as the hard coded one!
The admin page which has several apps under /home2/bogotob1/djangoproject:
The djangoproject/urls.py looks like this:
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # django default url(r'^$', 'djangoapp.views.home', name='home'), # admin url(r'^admin/', include(admin.site.urls)), # user authentication urls url(r'^accounts/', include('djangoapp.urls')), # blog url(r'^blogs/', include('blog.urls')), # forum url(r'^forums/', include('forum.urls')), )
Note that most of the apps are not complete and I keep working on them.
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization