Django Configuration - Serve Static Media w/Templates

I must say that Django documentation is all-around really fantastic. In fact, I've never run into a situation where I was totally stumped and their docs haven't saved the day. Regardless, there are always niches where you'll wish there was a slightly better real-world example - in this case regarding serving static media (stylesheets, javascript, image files, etc) on the development server. Their doc on this subject, found here, covers the base configuration pretty well however I still found that I couldn't get Django to recognize my static media for some reason. After messing with the config for a bit I managed to get it operational so If you're having the same problem, follow these steps and you'll have it running in no time.

The tutorial assumes basic knowledge of Django and that your project is located at the path (on OS X): '/Users/[USER_NAME]>/Code/Django/[PROJECT_NAME]' where USER_NAME is your OS X account and PROJECT_NAME is the top level directory of your project, likely where you ran the 'django-admin.py startproject [PROJECT_NAME]' command. For example, the path to my project is '/Users/john/Code/Django/testproj'. Obviously your code doesn't have to be on this exact path but you'll need to make sure you adjust the paths in the code below accordingly.

Note : In section two below I give two different ways to configure your settings.py file; The first way is with the paths hardcoded into the variables and the second is using python's built-in os module to create absolute paths to your static files. I kept both in here as a demonstration of how it works but I highly recommend going the absolute path route since your code will be portable across systems. Also, it should work on Windows without mods as well.

Configure URLconf - Make Static Media View Available for DEBUG Only


First, open the top-level urls.py file and add the following settings.DEBUG code after the urlpatterns that already reside there. The following is a basic example of my urls.py file:

from django.conf.urls.defaults import *
from testproj.base.views import index
from django.conf import settings

urlpatterns = patterns('',
     (r'^$', index),
)
if settings.DEBUG:
     urlpatterns += patterns('',(r'^static/(?P.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT}),
)


As explained in Django's documentation, it is recommended that in a production environment the server should provide the static files, not your Django code. Using the settings.DEBUG test will ensure that when you move it to production you'll catch the static files being served by Django since the DEBUG setting will be False in prod.

In the code you're importing the settings module from django.conf. The settings.DEBUG config is ensuring that any requests matching 'static/PATH' are served by the django.views.static.serve view with a context containing 'document_root' set to whatever path is found in settings.MEDIA_ROOT. Next we're going to set the value of that path in the settings.py file.

Configure Django Settings to the Location of Your Media


The first step is to create a directory named 'static' in the Django project folder and two directories within it named 'css' and 'scripts'. In the future you'll place your static files in folders within the main 'static' directory - the way you organize them doesn't make a difference just make sure it's a logical setup and that you adjust your template tags to point to the right folder (refer to the next section).

Option #1: Hardcoded Path


Open your settings.py file and modify the MEDIA_ROOT, MEDIA_UR, and ADMIN_MEDIA_PREFIX settings as follows (remembering to change the path to the location of your own static folder):
MEDIA_ROOT = '/Users/john/Code/Django/testproj/static/'

MEDIA_URL = '/static/'

ADMIN_MEDIA_PREFIX = '/media/'



Now, double-check that you didn't forget to add the beginning and ending '/' on each of the paths you modified as this will confuse Django. Note that while the ADMIN_MEDIA_PREFIX and MEDIA_URL don't necessarily have to be different, it is recommended by Django. If somehow you've wandered in here looking for instructions on how to do this on Windows I believe that the only difference in the entire tutorial is to change MEDIA_ROOT setting to 'C:/path/to/your/static/folder'. Following the rest of this should work on Windows but I didn't have time to validate that.

Option #2: Absolute Path option - Recommended


Instead of hardcoding as mentioned above, I'd recommend going the absolute path route since you can port your code from system to system without rewriting the settings.py file. Remember, either option should work but only use one way or the other.

Instead of hardcoding the paths into settings.py you'll import the os module and use the os.path.abspath('') method to acquire the working directory for your code dynamically and set it to ROOT_PATH. Then you'll adjust the same settings as before using the os.path.join method to attach your static directory. Refer to the code in settings.py below:

import os

ROOT_PATH = os.path.abspath('')
....
....
MEDIA_ROOT = os.path.join(ROOT_PATH,'static')
MEDIA_URL = os.path.join(ROOT_PATH,'static')
ADMIN_MEDIA_PREFIX = os.path.join(ROOT_PATH,'media')



Notice that when you use os.path.join(ROOT_PATH,'static') you won't put the '/' before and after the static directory as we did in the previous option.

Modify your Template to Point at the Static Directory


The final step is to make sure that in you've modified the HTML tags (script, link, etc) in your template to point at your 'static' directory. For example, here's how my script and link tags are configured for the example project:







The script src link is set to "/static/scripts/scripts.js" since this is where I've placed my javascript files. Again, don't forget to put the initial '/' at the beginning of your path.

Wrap it Up and Call it a Day


Test it out by running the 'python manage.py runserver' command from your project directory and everything should be working beautifully. If you run into problems it's likely that you've either forgotten or added a '/' in the wrong place on the paths you've configured.

0 comments:

Post a Comment

top