Skip to content

Commit

Permalink
Fixed #14693, #14709 -- Backwards incompatible change to rectify the …
Browse files Browse the repository at this point in the history
…confusion around the STATICFILES_URL and STATICFILES_ROOT settings.

  * Two new global settings that will be used by -- **but are not limited to** -- the staticfiles app: STATIC_ROOT and STATIC_URL.

  * Moving the 'django.contrib.staticfiles.templatetags.staticfiles' template tag to the core ('django.templatetags.static') and renaming it to 'get_static_prefix'.

  * Moving the context processor 'django.contrib.staticfiles.context_processors.staticfiles' to the core ('django.core.context_processors.static') and renaming it to 'static'.

  * Paths in media definitions will use STATIC_URL as the prefix if the value is not None, and falls back to the previously used MEDIA_URL.

Thanks again to the community for constructive criticism and Carl and Russ for sanity-inducing discussions on IRC.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14592 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
jezdez committed Nov 17, 2010
1 parent 9b45f6c commit 33d8fcd
Show file tree
Hide file tree
Showing 31 changed files with 908 additions and 329 deletions.
22 changes: 11 additions & 11 deletions django/conf/global_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
# 'django.core.context_processors.request',
'django.contrib.messages.context_processors.messages',
'django.contrib.staticfiles.context_processors.staticfiles',
)

# Output to use in template system for invalid (e.g. misspelled) variables.
Expand Down Expand Up @@ -256,13 +256,21 @@
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/"
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = ''

# URL that handles the media served from MEDIA_ROOT.
# Example: "http://media.lawrence.com"
# Example: "http://media.lawrence.com/media/"
MEDIA_URL = ''

# Absolute path to the directory that holds static files.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = ''

# URL that handles the static files served from STATIC_ROOT.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = None

# List of upload handler classes to be applied in order.
FILE_UPLOAD_HANDLERS = (
'django.core.files.uploadhandler.MemoryFileUploadHandler',
Expand Down Expand Up @@ -552,14 +560,6 @@
# STATICFILES #
###############

# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/static/"
STATICFILES_ROOT = ''

# URL that handles the static files served from STATICFILES_ROOT.
# Example: "http://media.lawrence.com/static/"
STATICFILES_URL = '/static/'

# A list of locations of additional static files
STATICFILES_DIRS = ()

Expand Down
12 changes: 6 additions & 6 deletions django/conf/project_template/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = ''

# Absolute path to the directory that holds media.
# Absolute path to the directory that holds static files.
# Example: "/home/media/media.lawrence.com/static/"
STATICFILES_ROOT = ''
STATIC_ROOT = ''

# URL that handles the static files served from STATICFILES_ROOT.
# Example: "http://static.lawrence.com/", "http://example.com/static/"
STATICFILES_URL = '/static/'
# URL that handles the static files served from STATIC_ROOT.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'

# URL prefix for admin media -- CSS, JavaScript and images.
# Make sure to use a trailing slash.
Expand Down
10 changes: 3 additions & 7 deletions django/contrib/admin/templatetags/adminmedia.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
from django.template import Library
from django.utils.encoding import iri_to_uri
from django.templatetags.static import PrefixNode

register = Library()

@register.simple_tag
def admin_media_prefix():
"""
Returns the string contained in the setting ADMIN_MEDIA_PREFIX.
"""
try:
from django.conf import settings
except ImportError:
return ''
return iri_to_uri(settings.ADMIN_MEDIA_PREFIX)
admin_media_prefix = register.simple_tag(admin_media_prefix)
return PrefixNode.handle_simple("ADMIN_MEDIA_PREFIX")
6 changes: 0 additions & 6 deletions django/contrib/staticfiles/context_processors.py

This file was deleted.

36 changes: 17 additions & 19 deletions django/contrib/staticfiles/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,44 @@
class StaticFilesHandler(WSGIHandler):
"""
WSGI middleware that intercepts calls to the static files directory, as
defined by the STATICFILES_URL setting, and serves those files.
defined by the STATIC_URL setting, and serves those files.
"""
def __init__(self, application, media_dir=None):
def __init__(self, application, base_dir=None):
self.application = application
if media_dir:
self.media_dir = media_dir
if base_dir:
self.base_dir = base_dir
else:
self.media_dir = self.get_media_dir()
self.media_url = urlparse(self.get_media_url())
if settings.DEBUG:
utils.check_settings()
self.base_dir = self.get_base_dir()
self.base_url = urlparse(self.get_base_url())
super(StaticFilesHandler, self).__init__()

def get_media_dir(self):
return settings.STATICFILES_ROOT
def get_base_dir(self):
return settings.STATIC_ROOT

def get_media_url(self):
return settings.STATICFILES_URL
def get_base_url(self):
if settings.DEBUG:
utils.check_settings()
return settings.STATIC_URL

def _should_handle(self, path):
"""
Checks if the path should be handled. Ignores the path if:
* the host is provided as part of the media_url
* the host is provided as part of the base_url
* the request's path isn't under the media path (or equal)
* settings.DEBUG isn't True
"""
return (self.media_url[2] != path and
path.startswith(self.media_url[2]) and not self.media_url[1])
return (self.base_url[2] != path and
path.startswith(self.base_url[2]) and not self.base_url[1])

def file_path(self, url):
"""
Returns the relative path to the media file on disk for the given URL.
The passed URL is assumed to begin with ``media_url``. If the
The passed URL is assumed to begin with ``base_url``. If the
resultant file path is outside the media directory, then a ValueError
is raised.
"""
# Remove ``media_url``.
relative_url = url[len(self.media_url[2]):]
relative_url = url[len(self.base_url[2]):]
return urllib.url2pathname(relative_url)

def serve(self, request):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
class Command(NoArgsCommand):
"""
Command that allows to copy or symlink media files from different
locations to the settings.STATICFILES_ROOT.
locations to the settings.STATIC_ROOT.
"""
option_list = NoArgsCommand.option_list + (
make_option('--noinput', action='store_false', dest='interactive',
Expand Down Expand Up @@ -85,7 +85,7 @@ def handle_noargs(self, **options):
self.stdout.write("\n%s static file%s %s to '%s'%s.\n"
% (actual_count, actual_count != 1 and 's' or '',
symlink and 'symlinked' or 'copied',
settings.STATICFILES_ROOT,
settings.STATIC_ROOT,
unmodified_count and ' (%s unmodified)'
% unmodified_count or ''))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
class Command(BaseRunserverCommand):
option_list = BaseRunserverCommand.option_list + (
make_option('--nostatic', action="store_false", dest='use_static_handler', default=True,
help='Tells Django to NOT automatically serve static files at STATICFILES_URL.'),
help='Tells Django to NOT automatically serve static files at STATIC_URL.'),
make_option('--insecure', action="store_true", dest='insecure_serving', default=False,
help='Allows serving static files even if DEBUG is False.'),
)
Expand Down
15 changes: 8 additions & 7 deletions django/contrib/staticfiles/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,22 @@ class StaticFilesStorage(FileSystemStorage):
Standard file system storage for site media files.
The defaults for ``location`` and ``base_url`` are
``STATICFILES_ROOT`` and ``STATICFILES_URL``.
``STATIC_ROOT`` and ``STATIC_URL``.
"""
def __init__(self, location=None, base_url=None, *args, **kwargs):
if location is None:
location = settings.STATICFILES_ROOT
location = settings.STATIC_ROOT
if base_url is None:
base_url = settings.STATICFILES_URL
base_url = settings.STATIC_URL
if not location:
raise ImproperlyConfigured("You're using the staticfiles app "
"without having set the STATICFILES_ROOT setting. Set it to "
"without having set the STATIC_ROOT setting. Set it to "
"the absolute path of the directory that holds static media.")
if not base_url:
# check for None since we might use a root URL (``/``)
if base_url is None:
raise ImproperlyConfigured("You're using the staticfiles app "
"without having set the STATICFILES_URL setting. Set it to "
"URL that handles the files served from STATICFILES_ROOT.")
"without having set the STATIC_URL setting. Set it to "
"URL that handles the files served from STATIC_ROOT.")
if settings.DEBUG:
utils.check_settings()
super(StaticFilesStorage, self).__init__(location, base_url, *args, **kwargs)
Expand Down
Empty file.
43 changes: 0 additions & 43 deletions django/contrib/staticfiles/templatetags/staticfiles.py

This file was deleted.

11 changes: 3 additions & 8 deletions django/contrib/staticfiles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,10 @@ def staticfiles_urlpatterns(prefix=None):
if not settings.DEBUG:
return []
if prefix is None:
prefix = settings.STATICFILES_URL
if not prefix:
prefix = settings.STATIC_URL
if not prefix or '://' in prefix:
raise ImproperlyConfigured(
"The prefix for the 'staticfiles_urlpatterns' helper is empty. "
"Make sure the STATICFILES_URL setting is set correctly.")
if '://' in prefix:
raise ImproperlyConfigured(
"The STATICFILES_URL setting is a full URL, not a path and "
"can't be used with the 'staticfiles_urlpatterns' helper.")
"The prefix for the 'staticfiles_urlpatterns' helper is invalid.")
if prefix.startswith("/"):
prefix = prefix[1:]
return patterns('',
Expand Down
16 changes: 8 additions & 8 deletions django/contrib/staticfiles/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ def is_ignored(path):

def check_settings():
"""
Checks if the MEDIA_(ROOT|URL) and STATICFILES_(ROOT|URL)
Checks if the MEDIA_(ROOT|URL) and STATIC_(ROOT|URL)
settings have the same value.
"""
if settings.MEDIA_URL == settings.STATICFILES_URL:
raise ImproperlyConfigured("The MEDIA_URL and STATICFILES_URL "
"settings must have individual values")
if ((settings.MEDIA_ROOT and settings.STATICFILES_ROOT) and
(settings.MEDIA_ROOT == settings.STATICFILES_ROOT)):
raise ImproperlyConfigured("The MEDIA_ROOT and STATICFILES_ROOT "
"settings must have individual values")
if settings.MEDIA_URL == settings.STATIC_URL:
raise ImproperlyConfigured("The MEDIA_URL and STATIC_URL "
"settings must have different values")
if ((settings.MEDIA_ROOT and settings.STATIC_ROOT) and
(settings.MEDIA_ROOT == settings.STATIC_ROOT)):
raise ImproperlyConfigured("The MEDIA_ROOT and STATIC_ROOT "
"settings must have different values")
7 changes: 7 additions & 0 deletions django/core/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ def i18n(request):

return context_extras

def static(request):
"""
Adds static-related context variables to the context.
"""
return {'STATIC_URL': settings.STATIC_URL}

def media(request):
"""
Adds media-related context variables to the context.
Expand Down
28 changes: 14 additions & 14 deletions django/core/servers/basehttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
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

from django.contrib.staticfiles import handlers, views as static

__version__ = "0.1"
__all__ = ['WSGIServer','WSGIRequestHandler']
Expand Down Expand Up @@ -635,34 +635,34 @@ def log_message(self, format, *args):
sys.stderr.write(msg)


class AdminMediaHandler(StaticFilesHandler):
class AdminMediaHandler(handlers.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 get_media_dir(self):
This is pending for deprecation since 1.3.
"""
def get_base_dir(self):
import django
return os.path.join(django.__path__[0], 'contrib', 'admin', 'media')

def get_media_url(self):
def get_base_url(self):
from django.conf import settings
return settings.ADMIN_MEDIA_PREFIX

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 ``media_url``. If the
resultant file path is outside the media directory, then a ValueError
The passed URL is assumed to begin with ``self.base_url``. If the
resulting file path is outside the media directory, then a ValueError
is raised.
"""
# Remove ``media_url``.
relative_url = url[len(self.media_url[2]):]
relative_url = url[len(self.base_url[2]):]
relative_path = urllib.url2pathname(relative_url)
return safe_join(self.media_dir, relative_path)
return safe_join(self.base_dir, relative_path)

def serve(self, request):
document_root, path = os.path.split(self.file_path(request.path))
Expand All @@ -673,10 +673,10 @@ def _should_handle(self, path):
"""
Checks if the path should be handled. Ignores the path if:
* the host is provided as part of the media_url
* the request's path isn't under the media path
* the host is provided as part of the base_url
* the request's path isn't under the base path
"""
return path.startswith(self.media_url[2]) and not self.media_url[1]
return path.startswith(self.base_url[2]) and not self.base_url[1]


def run(addr, port, wsgi_handler):
Expand Down
Loading

0 comments on commit 33d8fcd

Please sign in to comment.