import os import urllib import posixpath import mimetypes from django.core import template_loader from django.core.exceptions import Http404, ImproperlyConfigured from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect from django.core.template import Template, Context, TemplateDoesNotExist def serve(request, path, document_root=None, show_indexes=False): """ Serve static files below a given point in the directory structure. To use, put a URL pattern such as:: (r'^(?P.*)$', 'django.views.static.serve', {'document_root' : '/path/to/my/files/'}) in your URLconf. You must provide the ``document_root`` param. You may also set ``show_indexes`` to ``True`` if you'd like to serve a basic index of the directory. This index view will use the template hardcoded below, but if you'd like to override it, you can create a template called ``static/directory_index``. """ # Clean up given path to only allow serving files below document_root. path = posixpath.normpath(urllib.unquote(path)) newpath = '' for part in path.split('/'): if not part: # strip empty path components continue drive, part = os.path.splitdrive(part) head, part = os.path.split(part) if part in (os.curdir, os.pardir): # strip '.' amd '..' in path continue newpath = os.path.join(newpath, part) if newpath and path != newpath: return HttpResponseRedirect(newpath) fullpath = os.path.join(document_root, newpath) if os.path.isdir(fullpath): if show_indexes: return directory_index(newpath, fullpath) else: raise Http404, "Directory indexes are not allowed here." elif not os.path.exists(fullpath): raise Http404, '"%s" does not exist' % fullpath else: mimetype = mimetypes.guess_type(fullpath)[0] return HttpResponse(open(fullpath).read(), mimetype=mimetype) DEFAULT_DIRECTORY_INDEX_TEMPLATE = """ Index of {{ directory }}

Index of {{ directory }}

""" def directory_index(path, fullpath): try: t = template_loader.get_template('static/directory_index') except TemplateDoesNotExist: t = Template(DEFAULT_DIRECTORY_INDEX_TEMPLATE) files = [] for f in os.listdir(fullpath): if not f.startswith('.'): if os.path.isdir(os.path.join(fullpath, f)): f += '/' files.append(f) c = Context({ 'directory' : path + '/', 'file_list' : files, }) return HttpResponse(t.render(c))