diff options
| author | Jannis Leidel <jannis@leidel.info> | 2010-11-17 15:36:26 +0000 |
|---|---|---|
| committer | Jannis Leidel <jannis@leidel.info> | 2010-11-17 15:36:26 +0000 |
| commit | 33d8fcde8a317184a627492f008a4eab9333ed88 (patch) | |
| tree | 7c877854327c83aefdfaf00e727d26bd766e519e /django | |
| parent | 9b45f6cd5444423693715cc2a04d91a0de75060b (diff) | |
Fixed #14693, #14709 -- Backwards incompatible change to rectify the 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
Diffstat (limited to 'django')
| -rw-r--r-- | django/conf/global_settings.py | 22 | ||||
| -rw-r--r-- | django/conf/project_template/settings.py | 12 | ||||
| -rw-r--r-- | django/contrib/admin/templatetags/adminmedia.py | 10 | ||||
| -rw-r--r-- | django/contrib/staticfiles/context_processors.py | 6 | ||||
| -rw-r--r-- | django/contrib/staticfiles/handlers.py | 36 | ||||
| -rw-r--r-- | django/contrib/staticfiles/management/commands/collectstatic.py | 4 | ||||
| -rw-r--r-- | django/contrib/staticfiles/management/commands/runserver.py | 2 | ||||
| -rw-r--r-- | django/contrib/staticfiles/storage.py | 15 | ||||
| -rw-r--r-- | django/contrib/staticfiles/templatetags/__init__.py | 0 | ||||
| -rw-r--r-- | django/contrib/staticfiles/templatetags/staticfiles.py | 43 | ||||
| -rw-r--r-- | django/contrib/staticfiles/urls.py | 11 | ||||
| -rw-r--r-- | django/contrib/staticfiles/utils.py | 16 | ||||
| -rw-r--r-- | django/core/context_processors.py | 7 | ||||
| -rw-r--r-- | django/core/servers/basehttp.py | 28 | ||||
| -rw-r--r-- | django/forms/widgets.py | 20 | ||||
| -rw-r--r-- | django/templatetags/static.py | 84 | ||||
| -rw-r--r-- | django/views/static.py | 4 |
17 files changed, 179 insertions, 141 deletions
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 3aa333ba91..191a463ac8 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -195,9 +195,9 @@ TEMPLATE_CONTEXT_PROCESSORS = ( '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. @@ -256,13 +256,21 @@ SECRET_KEY = '' 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', @@ -552,14 +560,6 @@ FIXTURE_DIRS = () # 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 = () diff --git a/django/conf/project_template/settings.py b/django/conf/project_template/settings.py index 1d33dd13c9..e0265579b8 100644 --- a/django/conf/project_template/settings.py +++ b/django/conf/project_template/settings.py @@ -49,16 +49,16 @@ MEDIA_ROOT = '' # 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. diff --git a/django/contrib/admin/templatetags/adminmedia.py b/django/contrib/admin/templatetags/adminmedia.py index 5429810eb9..3b1c39b3a7 100644 --- a/django/contrib/admin/templatetags/adminmedia.py +++ b/django/contrib/admin/templatetags/adminmedia.py @@ -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") diff --git a/django/contrib/staticfiles/context_processors.py b/django/contrib/staticfiles/context_processors.py deleted file mode 100644 index 3ed00719e1..0000000000 --- a/django/contrib/staticfiles/context_processors.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.conf import settings - -def staticfiles(request): - return { - 'STATICFILES_URL': settings.STATICFILES_URL, - } diff --git a/django/contrib/staticfiles/handlers.py b/django/contrib/staticfiles/handlers.py index 20b04960da..2b7276133f 100644 --- a/django/contrib/staticfiles/handlers.py +++ b/django/contrib/staticfiles/handlers.py @@ -10,46 +10,44 @@ from django.contrib.staticfiles.views import serve 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): diff --git a/django/contrib/staticfiles/management/commands/collectstatic.py b/django/contrib/staticfiles/management/commands/collectstatic.py index d121223595..8882ae20db 100644 --- a/django/contrib/staticfiles/management/commands/collectstatic.py +++ b/django/contrib/staticfiles/management/commands/collectstatic.py @@ -12,7 +12,7 @@ from django.contrib.staticfiles import finders 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', @@ -85,7 +85,7 @@ Type 'yes' to continue, or 'no' to cancel: """) 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 '')) diff --git a/django/contrib/staticfiles/management/commands/runserver.py b/django/contrib/staticfiles/management/commands/runserver.py index e13875994b..f4c22598c3 100644 --- a/django/contrib/staticfiles/management/commands/runserver.py +++ b/django/contrib/staticfiles/management/commands/runserver.py @@ -8,7 +8,7 @@ from django.contrib.staticfiles.handlers import StaticFilesHandler 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.'), ) diff --git a/django/contrib/staticfiles/storage.py b/django/contrib/staticfiles/storage.py index b4bfea74d4..eb0eabf861 100644 --- a/django/contrib/staticfiles/storage.py +++ b/django/contrib/staticfiles/storage.py @@ -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) diff --git a/django/contrib/staticfiles/templatetags/__init__.py b/django/contrib/staticfiles/templatetags/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/django/contrib/staticfiles/templatetags/__init__.py +++ /dev/null diff --git a/django/contrib/staticfiles/templatetags/staticfiles.py b/django/contrib/staticfiles/templatetags/staticfiles.py deleted file mode 100644 index 6153f5a385..0000000000 --- a/django/contrib/staticfiles/templatetags/staticfiles.py +++ /dev/null @@ -1,43 +0,0 @@ -from django import template -from django.utils.encoding import iri_to_uri - -register = template.Library() - -class StaticFilesPrefixNode(template.Node): - - def __init__(self, varname=None): - self.varname = varname - - def render(self, context): - try: - from django.conf import settings - except ImportError: - prefix = '' - else: - prefix = iri_to_uri(settings.STATICFILES_URL) - if self.varname is None: - return prefix - context[self.varname] = prefix - return '' - -@register.tag -def get_staticfiles_prefix(parser, token): - """ - Populates a template variable with the prefix (settings.STATICFILES_URL). - - Usage:: - - {% get_staticfiles_prefix [as varname] %} - - Examples:: - - {% get_staticfiles_prefix %} - {% get_staticfiles_prefix as staticfiles_prefix %} - - """ - tokens = token.contents.split() - if len(tokens) > 1 and tokens[1] != 'as': - raise template.TemplateSyntaxError( - "First argument in '%s' must be 'as'" % tokens[0]) - return StaticFilesPrefixNode(varname=(len(tokens) > 1 and tokens[2] or None)) - diff --git a/django/contrib/staticfiles/urls.py b/django/contrib/staticfiles/urls.py index 70f04f2ec9..aa4ab459d1 100644 --- a/django/contrib/staticfiles/urls.py +++ b/django/contrib/staticfiles/urls.py @@ -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('', diff --git a/django/contrib/staticfiles/utils.py b/django/contrib/staticfiles/utils.py index 0071dbd370..428bb69b1e 100644 --- a/django/contrib/staticfiles/utils.py +++ b/django/contrib/staticfiles/utils.py @@ -33,13 +33,13 @@ def get_files(storage, ignore_patterns=[], location=''): 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") diff --git a/django/core/context_processors.py b/django/core/context_processors.py index 7a59728bfc..fa05d425f6 100644 --- a/django/core/context_processors.py +++ b/django/core/context_processors.py @@ -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. diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index 9c92a88b44..9c3e90043b 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -17,8 +17,8 @@ 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 + +from django.contrib.staticfiles import handlers, views as static __version__ = "0.1" __all__ = ['WSGIServer','WSGIRequestHandler'] @@ -635,19 +635,20 @@ class WSGIRequestHandler(BaseHTTPRequestHandler): 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 @@ -655,14 +656,13 @@ class AdminMediaHandler(StaticFilesHandler): """ 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)) @@ -673,10 +673,10 @@ class AdminMediaHandler(StaticFilesHandler): """ 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): diff --git a/django/forms/widgets.py b/django/forms/widgets.py index cb12586d6c..8eb5fef3e7 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -1,9 +1,13 @@ """ HTML Widget classes """ +import datetime +from itertools import chain +import time +from urlparse import urljoin +from util import flatatt import django.utils.copycompat as copy -from itertools import chain from django.conf import settings from django.utils.datastructures import MultiValueDict, MergeDict from django.utils.html import escape, conditional_escape @@ -11,10 +15,6 @@ from django.utils.translation import ugettext, ugettext_lazy from django.utils.encoding import StrAndUnicode, force_unicode from django.utils.safestring import mark_safe from django.utils import datetime_safe, formats -import time -import datetime -from util import flatatt -from urlparse import urljoin __all__ = ( 'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'PasswordInput', @@ -63,10 +63,16 @@ class Media(StrAndUnicode): for path in self._css[medium]] for medium in media]) - def absolute_path(self, path): + def absolute_path(self, path, prefix=None): if path.startswith(u'http://') or path.startswith(u'https://') or path.startswith(u'/'): return path - return urljoin(settings.MEDIA_URL,path) + if prefix is None: + if settings.STATIC_URL is None: + # backwards compatibility + prefix = settings.MEDIA_URL + else: + prefix = settings.STATIC_URL + return urljoin(prefix, path) def __getitem__(self, name): "Returns a Media object that only contains media of the given type" diff --git a/django/templatetags/static.py b/django/templatetags/static.py new file mode 100644 index 0000000000..97d657189b --- /dev/null +++ b/django/templatetags/static.py @@ -0,0 +1,84 @@ +from django import template +from django.utils.encoding import iri_to_uri + +register = template.Library() + +class PrefixNode(template.Node): + + def __repr__(self): + return "<PrefixNode for %r>" % self.name + + def __init__(self, varname=None, name=None): + if name is None: + raise template.TemplateSyntaxError( + "Prefix nodes must be given a name to return.") + self.varname = varname + self.name = name + + @classmethod + def handle_token(cls, parser, token, name): + """ + Class method to parse prefix node and return a Node. + """ + tokens = token.contents.split() + if len(tokens) > 1 and tokens[1] != 'as': + raise template.TemplateSyntaxError( + "First argument in '%s' must be 'as'" % tokens[0]) + if len(tokens) > 1: + varname = tokens[2] + else: + varname = None + return cls(varname, name) + + @classmethod + def handle_simple(cls, name): + try: + from django.conf import settings + except ImportError: + prefix = '' + else: + prefix = iri_to_uri(getattr(settings, name, '')) + return prefix + + def render(self, context): + prefix = self.handle_simple(self.name) + if self.varname is None: + return prefix + context[self.varname] = prefix + return '' + +@register.tag +def get_static_prefix(parser, token): + """ + Populates a template variable with the static prefix, + ``settings.STATIC_URL``. + + Usage:: + + {% get_static_prefix [as varname] %} + + Examples:: + + {% get_static_prefix %} + {% get_static_prefix as static_prefix %} + + """ + return PrefixNode.handle_token(parser, token, "STATIC_URL") + +@register.tag +def get_media_prefix(parser, token): + """ + Populates a template variable with the static prefix, + ``settings.MEDIA_URL``. + + Usage:: + + {% get_media_prefix [as varname] %} + + Examples:: + + {% get_media_prefix %} + {% get_media_prefix as media_prefix %} + + """ + return PrefixNode.handle_token(parser, token, "MEDIA_URL") diff --git a/django/views/static.py b/django/views/static.py index a4a4c8db7c..2ce886f7ac 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -17,8 +17,8 @@ from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpRespons from django.template import Template, Context, TemplateDoesNotExist from django.utils.http import http_date -from django.contrib.staticfiles.views import \ - directory_index, was_modified_since, serve as staticfiles_serve +from django.contrib.staticfiles.views import (directory_index, + was_modified_since, serve as staticfiles_serve) def serve(request, path, document_root=None, show_indexes=False, insecure=False): |
