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:
@@ -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}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user