import os
import mimetypes
from django.conf import settings
from django.shortcuts import Http404
from django.http import HttpResponse
def serve_apps(request, appname, path):
"""
Serve static files from media folders in all installed apps
To use put a URL pattern such as:
(r'^media/(?P<appname>\w+)/(?P<path>.+)$', 'media.serve_apps')
Then the media in my_installed_app/media will be available at the url media/my_installed_app
This view is intended for development purposes only and you should properly configure your
webserver to serve media in production use.
"""
for app in settings.INSTALLED_APPS:
# Split of the last part of the app name; e.g. 'django.contrib.admin' -> 'admin'
app_short_name = app.rpartition('.')[2]
if app_short_name == appname:
# Work out the directory in which this module resides
mod = __import__(app)
moddir = os.path.dirname(mod.__file__)
abspath = os.path.join(moddir, 'media', path)
if not os.path.exists(abspath):
raise Http404("Could not find media '%s' for app '%s' at location '%s'" % (path, appname, abspath))
if not os.path.isfile(abspath):
raise Http404("Media '%s' at '%s' is not a file" % (path, abspath))
# Return the file as a response guessing the mimetype
mimetype = mimetypes.guess_type(abspath)[0] or 'application/octet-stream'
contents = open(abspath, 'rb').read()
response = HttpResponse(contents, mimetype=mimetype)
response["Content-Length"] = len(contents)
return response
raise Http404("Could not find app of name '%s'" % (appname,))
Comments
A good Idea, but i think serving media files should be the job of an apache webserver or lighttpd or something similar. It would me more usefull to make the media directory in every app a good practice and then to make symbolic links in your real media directory.
#
phxx: Um, the suggested usage clearly indicates this is for development use, not production.
This is a great idea. It liberates me from making all those symlinks, which become a huge pain when multiple developers are working on the same project on different systems with different path setups. +1 from me, wish I'd thought of it!
#
Oh right. I've overseen the
if settings.DEBUG.#
I also have project-wide media in MEDIA_ROOT that I'd like to have served at media/. I just removed the final line (raise Http404...) and replaced it with this:
And added this near the top:
#
One other note - this code is Python 2.5 specific as written. It can easily be made compatible with previous versions by replacing this line:
with:
#
THERE IS A NEWER VERSION OF THIS SNIPPET
@carljm:
Thanks for the comments. Your use case is exactly the same as mine (collaborating in development). I have rewritten the snippet as Snippet 985 with the document_root feature as you suggested.
As for the python2.5 suggestion: I have moved the new snippet to using
runpyrather than__import__since it seems better at finding a__file__attribute. So the new version is heavily 2.5 dependent.#