1
0
mirror of https://github.com/django/django.git synced 2025-11-07 07:15:35 +00:00

Fixed #12323 and #11582 -- Extended the ability to handle static files. Thanks to all for helping with the original app, the patch, documentation and general support.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14293 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jannis Leidel
2010-10-20 01:33:24 +00:00
parent a014ee0288
commit cfc19f84de
54 changed files with 2008 additions and 313 deletions

View File

@@ -71,7 +71,15 @@ def media(request):
Adds media-related context variables to the context.
"""
return {'MEDIA_URL': settings.MEDIA_URL}
import warnings
warnings.warn(
"The context processor at `django.core.context_processors.media` is " \
"deprecated; use the path `django.contrib.staticfiles.context_processors.staticfiles` " \
"instead.",
PendingDeprecationWarning
)
from django.contrib.staticfiles.context_processors import staticfiles as staticfiles_context_processor
return staticfiles_context_processor(request)
def request(request):
return {'request': request}

View File

@@ -1,7 +1,9 @@
from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
import os
import sys
import warnings
from django.core.management.base import BaseCommand, CommandError
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
@@ -20,6 +22,7 @@ class Command(BaseCommand):
import django
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
from django.core.handlers.wsgi import WSGIHandler
from django.contrib.staticfiles.handlers import StaticFilesHandler
if args:
raise CommandError('Usage is runserver %s' % self.args)
if not addrport:
@@ -56,7 +59,10 @@ class Command(BaseCommand):
translation.activate(settings.LANGUAGE_CODE)
try:
handler = AdminMediaHandler(WSGIHandler(), admin_media_path)
handler = WSGIHandler()
handler = StaticFilesHandler(handler)
# serve admin media like old-school (deprecation pending)
handler = AdminMediaHandler(handler, admin_media_path)
run(addr, int(port), handler)
except WSGIServerException, e:
# Use helpful error messages instead of ugly tracebacks.

View File

@@ -8,16 +8,17 @@ been reviewed for security issues. Don't use it for production use.
"""
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import mimetypes
import os
import re
import stat
import sys
import urllib
import warnings
from django.core.management.color import color_style
from django.utils.http import http_date
from django.utils._os import safe_join
from django.contrib.staticfiles.handlers import StaticFilesHandler
from django.views import static
__version__ = "0.1"
__all__ = ['WSGIServer','WSGIRequestHandler']
@@ -633,86 +634,46 @@ class WSGIRequestHandler(BaseHTTPRequestHandler):
sys.stderr.write(msg)
class AdminMediaHandler(object):
class AdminMediaHandler(StaticFilesHandler):
"""
WSGI middleware that intercepts calls to the admin media directory, as
defined by the ADMIN_MEDIA_PREFIX setting, and serves those images.
Use this ONLY LOCALLY, for development! This hasn't been tested for
security and is not super efficient.
"""
def __init__(self, application, media_dir=None):
def get_media_dir(self):
import django
return os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
def get_media_url(self):
from django.conf import settings
self.application = application
if not media_dir:
import django
self.media_dir = \
os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
else:
self.media_dir = media_dir
self.media_url = settings.ADMIN_MEDIA_PREFIX
return settings.ADMIN_MEDIA_PREFIX
def __init__(self, application, media_dir=None):
warnings.warn('The AdminMediaHandler handler is deprecated; use the '
'`django.contrib.staticfiles.handlers.StaticFilesHandler` instead.',
PendingDeprecationWarning)
super(AdminMediaHandler, self).__init__(application, media_dir)
def file_path(self, url):
"""
Returns the path to the media file on disk for the given URL.
The passed URL is assumed to begin with ADMIN_MEDIA_PREFIX. If the
The passed URL is assumed to begin with ``media_url``. If the
resultant file path is outside the media directory, then a ValueError
is raised.
"""
# Remove ADMIN_MEDIA_PREFIX.
# Remove ``media_url``.
relative_url = url[len(self.media_url):]
relative_path = urllib.url2pathname(relative_url)
return safe_join(self.media_dir, relative_path)
def __call__(self, environ, start_response):
import os.path
def serve(self, request, path):
document_root, path = os.path.split(path)
return static.serve(request, path, document_root=document_root)
# Ignore requests that aren't under ADMIN_MEDIA_PREFIX. Also ignore
# all requests if ADMIN_MEDIA_PREFIX isn't a relative URL.
if self.media_url.startswith('http://') or self.media_url.startswith('https://') \
or not environ['PATH_INFO'].startswith(self.media_url):
return self.application(environ, start_response)
# Find the admin file and serve it up, if it exists and is readable.
try:
file_path = self.file_path(environ['PATH_INFO'])
except ValueError: # Resulting file path was not valid.
status = '404 NOT FOUND'
headers = {'Content-type': 'text/plain'}
output = ['Page not found: %s' % environ['PATH_INFO']]
start_response(status, headers.items())
return output
if not os.path.exists(file_path):
status = '404 NOT FOUND'
headers = {'Content-type': 'text/plain'}
output = ['Page not found: %s' % environ['PATH_INFO']]
else:
try:
fp = open(file_path, 'rb')
except IOError:
status = '401 UNAUTHORIZED'
headers = {'Content-type': 'text/plain'}
output = ['Permission denied: %s' % environ['PATH_INFO']]
else:
# This is a very simple implementation of conditional GET with
# the Last-Modified header. It makes media files a bit speedier
# because the files are only read off disk for the first
# request (assuming the browser/client supports conditional
# GET).
mtime = http_date(os.stat(file_path)[stat.ST_MTIME])
headers = {'Last-Modified': mtime}
if environ.get('HTTP_IF_MODIFIED_SINCE', None) == mtime:
status = '304 NOT MODIFIED'
output = []
else:
status = '200 OK'
mime_type = mimetypes.guess_type(file_path)[0]
if mime_type:
headers['Content-Type'] = mime_type
output = [fp.read()]
fp.close()
start_response(status, headers.items())
return output
def run(addr, port, wsgi_handler):
server_address = (addr, port)