Serve static media files from app/media subdirectory

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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,))

More like this

  1. Serve static media and indexes from app directories [Python2.5, Development only] by adamlofts 5 years, 8 months ago
  2. staticview for app by limodou 6 years, 10 months ago
  3. Custom mod_python AuthenHandler by aeby 6 years, 8 months ago
  4. Use the WSGIAccessScript Directive to secure static files based on the Django session by LuckiDog 2 years, 11 months ago
  5. Automagically import settings from installed applications by jezdez 6 years, 2 months ago

Comments

phxx (on August 5, 2008):

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.

#

carljm (on August 5, 2008):

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!

#

phxx (on August 5, 2008):

Oh right. I've overseen the if settings.DEBUG.

#

carljm (on August 5, 2008):

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:

# if app not found, fall back to regular static serve from MEDIA_ROOT
full_path = "%s/%s" % (appname, path)
return serve(request, path=full_path, document_root=settings.MEDIA_ROOT)

And added this near the top:

from django.views.static import serve

#

carljm (on August 14, 2008):

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:

app_short_name = app.rpartition('.')[2]

with:

app_short_name = app.rsplit('.', 1)[-1]

#

(Forgotten your password?)