Django itself doesn’t serve static (media) files, such as images, style sheets, or video. It leaves that job to whichever Web server you choose.
The reasoning here is that standard Web servers, such as Apache, lighttpd and Cherokee, are much more fine-tuned at serving static files than a Web application framework.
With that said, Django does support static files during development. You can use the django.views.static.serve() view to serve media files.
See also
If you just need to serve the admin media from a nonstandard location, see the --adminmedia parameter to runserver.
Using this method is inefficient and insecure. Do not use this in a production setting. Use this only for development.
For information on serving static files in an Apache production environment, see the Django mod_python documentation.
Here’s the formal definition of the serve() view:
To use it, just put this in your URLconf:
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': '/path/to/media'}),
...where site_media is the URL where your media will be rooted, and /path/to/media is the filesystem root for your media. This will call the serve() view, passing in the path from the URLconf and the (required) document_root parameter.
Given the above URLconf:
Of course, it's not compulsory to use a fixed string for the 'document_root' value. You might wish to make that an entry in your settings file and use the setting value there. That will allow you and other developers working on the code to easily change the value as required. For example, if we have a line in settings.py that says:
STATIC_DOC_ROOT = '/path/to/media'
...we could write the above URLconf entry as:
from django.conf import settings
...
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_DOC_ROOT}),
Be careful not to use the same path as your ADMIN_MEDIA_PREFIX (which defaults to /media/) as this will overwrite your URLconf entry.
Optionally, you can pass the show_indexes parameter to the serve() view. This is False by default. If it's True, Django will display file listings for directories.
For example:
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': '/path/to/media', 'show_indexes': True}),
You can customize the index view by creating a template called static/directory_index.html. That template gets two objects in its context:
Here's the default static/directory_index.html template:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en-us" />
<meta name="robots" content="NONE,NOARCHIVE" />
<title>Index of {{ directory }}</title>
</head>
<body>
<h1>Index of {{ directory }}</h1>
<ul>
{% for f in file_list %}
<li><a href="{{ f }}">{{ f }}</a></li>
{% endfor %}
</ul>
</body>
</html>
Because URLconfs are just plain Python modules, you can use Python logic to make the static-media view available only in development mode. This is a handy trick to make sure the static-serving view doesn't slip into a production setting by mistake.
Do this by wrapping an if DEBUG statement around the django.views.static.serve() inclusion. Here's a full example URLconf:
from django.conf.urls.defaults import *
from django.conf import settings
urlpatterns = patterns('',
(r'^articles/2003/$', 'news.views.special_case_2003'),
(r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'),
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'),
)
if settings.DEBUG:
urlpatterns += patterns('',
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
)
This code is straightforward. It imports the settings and checks the value of the DEBUG setting. If it evaluates to True, then site_media will be associated with the django.views.static.serve view. If not, then the view won't be made available.
Of course, the catch here is that you'll have to remember to set DEBUG=False in your production settings file. But you should be doing that anyway.
Sep 20, 2009