This view serves static media and directory indexes for a django application. It should only be used in development, media should be provided directly by a web server in production.
This view assumes a django application stores its media in app/media (which is very common) and the file is referred to in the templates by the last part of a django app path. e.g. As in django.contrib.admin -> 'admin'.
First we check if the media is a request in an application directory; if so we attempt to serve it from there. Then we attempt to provide the document from the document_root parameter (if provided).
To use this view you should add something like the following to urls.py:
if settings.DEBUG:
urlpatterns += (r'^media/(?P<path>.*)$', 'site.media.serve_apps', {'document_root' : settings.MEDIA_ROOT})
You can then have the admin media files served by setting ADMIN_MEDIA_PREFIX = '/media/admin/'
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | import os
import mimetypes
from django.conf import settings
from django.shortcuts import Http404
from django.http import HttpResponse
from django.views.static import directory_index
from runpy import run_module
def serve_apps(request, path, document_root=None):
"""
This view serves static media and directory indexes for a django application. It should
only be used in development, media should be provided directly by a web server in production.
This view assumes a django application stores its media in app/media (which is very common) and
the file is referred to in the templates by the last part of a django app path. e.g. As in
django.contrib.admin -> 'admin'.
First we check if the media is a request in an application directory; if so we attempt to serve
it from there. Then we attempt to provide the document from the document_root parameter (if
provided).
To use this view you should add something like the following to urls.py:
if settings.DEBUG:
urlpatterns += (r'^media/(?P<path>.*)$', 'site.media.serve_apps', {'document_root' : settings.MEDIA_ROOT})
You can then have the admin media files served by setting
ADMIN_MEDIA_PREFIX = '/media/admin/'
"""
def find_abspath(path, document_root):
pathsplit = path.split(os.sep)
# Look for the file in installed apps
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 == pathsplit[0]:
# Work out the directory in which this module resides. This works better than using
# mod = __import__(app)
mod = run_module(app)
moddir = os.path.dirname(mod['__file__'])
return os.path.join(moddir, 'media', *pathsplit[1:])
# Look for the file in document_root
if document_root:
return os.path.join(document_root, path)
return None
abspath = find_abspath(path, document_root) or ''
if not os.path.exists(abspath):
raise Http404("No media found for path %s (tried '%s')" % (path, abspath))
if os.path.isdir(abspath):
# To make the template work a directory must have a trailing slash in the url
# The one exception is when path == /
if not path.endswith('/') and path:
raise Http404("This path is a directory. Add a trailing slash to view index")
return directory_index(path[:-1], abspath)
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
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
hello, I get an internal server error 'str' object has no attribute 'resolve'
#
Thank you for a great snippet. It saved hours for me)
To make it work for me, I had to make some corrections (maybe the reason is that I'm on Windows):
line 31: replace 'os.sep' with '"/"'. Correct me if I'm wrong, but since 'path' is taken from url, it always contains forward slashes.
line 40: replace 'run_module' with
'__import__'
. The former just doesn't work for me (maybe because of Windows again)line 41: replace all with 'moddir = mod.
'__path__[0]'
. This follows from the previous correction.I've also made some adjustments to the script according to my pattern of naming media folders. I store media in app/media/media_type/app/ folders, e.g. js files in app/media/js/app/ etc. If someone uses the same pattern and needs these adjustments, feel free to ask me.
#
Please login first before commenting.