Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
  • Loading branch information...
commit 33d8fcde8a317184a627492f008a4eab9333ed88 1 parent 9b45f6c
@jezdez jezdez authored
Showing with 908 additions and 329 deletions.
  1. +11 −11 django/conf/global_settings.py
  2. +6 −6 django/conf/project_template/settings.py
  3. +3 −7 django/contrib/admin/templatetags/adminmedia.py
  4. +0 −6 django/contrib/staticfiles/context_processors.py
  5. +17 −19 django/contrib/staticfiles/handlers.py
  6. +2 −2 django/contrib/staticfiles/management/commands/collectstatic.py
  7. +1 −1  django/contrib/staticfiles/management/commands/runserver.py
  8. +8 −7 django/contrib/staticfiles/storage.py
  9. 0  django/contrib/staticfiles/templatetags/__init__.py
  10. +0 −43 django/contrib/staticfiles/templatetags/staticfiles.py
  11. +3 −8 django/contrib/staticfiles/urls.py
  12. +8 −8 django/contrib/staticfiles/utils.py
  13. +7 −0 django/core/context_processors.py
  14. +14 −14 django/core/servers/basehttp.py
  15. +13 −7 django/forms/widgets.py
  16. +84 −0 django/templatetags/static.py
  17. +2 −2 django/views/static.py
  18. +30 −30 docs/howto/static-files.txt
  19. +1 −1  docs/man/django-admin.1
  20. +61 −61 docs/ref/contrib/staticfiles.txt
  21. +0 −29 docs/ref/django-admin.txt
  22. +54 −6 docs/ref/settings.txt
  23. +11 −2 docs/ref/templates/api.txt
  24. +2 −4 docs/releases/1.3-alpha-1.txt
  25. +41 −4 docs/releases/1.3-alpha-2.txt
  26. +1 −1  docs/releases/1.3.txt
  27. +1 −0  docs/releases/index.txt
  28. +32 −9 docs/topics/forms/media.txt
  29. +460 −0 tests/regressiontests/forms/tests/media.py
  30. +15 −35 tests/regressiontests/staticfiles_tests/tests.py
  31. +20 −6 tests/regressiontests/templates/tests.py
View
22 django/conf/global_settings.py
@@ -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.
@@ -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',
@@ -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 = ()
View
12 django/conf/project_template/settings.py
@@ -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.
View
10 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")
View
6 django/contrib/staticfiles/context_processors.py
@@ -1,6 +0,0 @@
-from django.conf import settings
-
-def staticfiles(request):
- return {
- 'STATICFILES_URL': settings.STATICFILES_URL,
- }
View
36 django/contrib/staticfiles/handlers.py
@@ -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):
View
4 django/contrib/staticfiles/management/commands/collectstatic.py
@@ -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',
@@ -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 ''))
View
2  django/contrib/staticfiles/management/commands/runserver.py
@@ -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.'),
)
View
15 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)
View
0  django/contrib/staticfiles/templatetags/__init__.py
No changes.
View
43 django/contrib/staticfiles/templatetags/staticfiles.py
@@ -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))
-
View
11 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('',
View
16 django/contrib/staticfiles/utils.py
@@ -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")
View
7 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.
View
28 django/core/servers/basehttp.py
@@ -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']
@@ -635,19 +635,20 @@ 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
@@ -655,14 +656,13 @@ 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))
@@ -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):
View
20 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.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 @@ def render_css(self):
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"
View
84 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")
View
4 django/views/static.py
@@ -17,8 +17,8 @@
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):
View
60 docs/howto/static-files.txt
@@ -50,12 +50,12 @@ Here's the basic usage in a nutshell:
First, you'll need to make sure that ``django.contrib.staticfiles`` is in
your :setting:`INSTALLED_APPS`.
- Next, you'll need to edit :setting:`STATICFILES_ROOT` to point to where
+ Next, you'll need to edit :setting:`STATIC_ROOT` to point to where
you'd like your static media stored. For example::
- STATICFILES_ROOT = "/home/jacob/projects/mysite.com/static_media"
+ STATIC_ROOT = "/home/jacob/projects/mysite.com/static_media"
- You may also want to set the :setting:`STATICFILES_URL` setting at this
+ You may also want to set the :setting:`STATIC_URL` setting at this
time, though the default value (of ``/static/``) is perfect for local
development.
@@ -69,7 +69,7 @@ Here's the basic usage in a nutshell:
./manage.py collectstatic
This'll churn through your static file storage and move them into the
- directory given by :setting:`STATICFILES_ROOT`. (This is not necessary
+ directory given by :setting:`STATIC_ROOT`. (This is not necessary
in local development if you are using :djadmin:`runserver` or adding
``staticfiles_urlpatterns`` to your URLconf; see below).
@@ -78,7 +78,7 @@ Here's the basic usage in a nutshell:
If you're using the built-in development server (the
:djadmin:`runserver` management command) and have the :setting:`DEBUG`
setting set to ``True``, your staticfiles will automatically be served
- from :setting:`STATICFILES_URL` in development.
+ from :setting:`STATIC_URL` in development.
If you are using some other server for local development, you can
quickly serve static media locally by adding::
@@ -98,7 +98,7 @@ Here's the basic usage in a nutshell:
.. code-block:: html+django
- <img src="{{ STATICFILES_URL }}images/hi.jpg />
+ <img src="{{ STATIC_URL }}images/hi.jpg />
See :ref:`staticfiles-in-templates` for more details, including an
alternate method (using a template tag).
@@ -115,7 +115,7 @@ the framework see :doc:`the staticfiles reference </ref/contrib/staticfiles>`.
app is to make it easier to keep static files separate from user-uploaded
files. For this reason, you will probably want to make your
:setting:`MEDIA_ROOT` and :setting:`MEDIA_URL` different from your
- :setting:`STATICFILES_ROOT` and :setting:`STATICFILES_URL`. You will need to
+ :setting:`STATIC_ROOT` and :setting:`STATIC_URL`. You will need to
arrange for serving of files in :setting:`MEDIA_ROOT` yourself;
``staticfiles`` does not deal with user-uploaded media at all.
@@ -136,7 +136,7 @@ development, and it makes it *very* hard to change where you've deployed your
media. If, for example, you wanted to switch to using a content delivery network
(CDN), then you'd need to change more or less every single template.
-A far better way is to use the value of the :setting:`STATICFILES_URL` setting
+A far better way is to use the value of the :setting:`STATIC_URL` setting
directly in your templates. This means that a switch of media servers only
requires changing that single value. Much better!
@@ -147,7 +147,7 @@ With a context processor
------------------------
The included context processor is the easy way. Simply make sure
-``'django.contrib.staticfiles.context_processors.staticfiles'`` is in your
+``'django.core.context_processors.static'`` is in your
:setting:`TEMPLATE_CONTEXT_PROCESSORS`. It's there by default, and if you're
editing that setting by hand it should look something like::
@@ -155,18 +155,18 @@ editing that setting by hand it should look something like::
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
+ 'django.core.context_processors.static',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
- 'django.contrib.staticfiles.context_processors.staticfiles',
)
-Once that's done, you can refer to :setting:`STATICFILES_URL` in your templates:
+Once that's done, you can refer to :setting:`STATIC_URL` in your templates:
.. code-block:: html+django
- <img src="{{ STATICFILES_URL }}images/hi.jpg />
+ <img src="{{ STATIC_URL }}images/hi.jpg />
-If ``{{ STATICFILES_URL }}`` isn't working in your template, you're probably not
+If ``{{ STATIC_URL }}`` isn't working in your template, you're probably not
using :class:`~django.template.RequestContext` when rendering the template.
As a brief refresher, context processors add variables into the contexts of
@@ -180,23 +180,23 @@ To see how that works, and to read more details, check out
With a template tag
-------------------
-The second option is the :ttag:`get_staticfiles_prefix` template tag. You can
+The second option is the :ttag:`get_static_prefix` template tag. You can
use this if you're not using :class:`~django.template.RequestContext`, or if you
-need more control over exactly where and how :setting:`STATICFILES_URL` is
+need more control over exactly where and how :setting:`STATIC_URL` is
injected into the template. Here's an example:
.. code-block:: html+django
- {% load staticfiles %}
- <img src="{% get_staticfiles_prefix %}images/hi.jpg" />
+ {% load static %}
+ <img src="{% get_static_prefix %}images/hi.jpg" />
There's also a second form you can use to avoid extra processing if you need the
value multiple times:
.. code-block:: html+django
- {% load staticfiles %}
- {% get_staticfiles_prefix as STATIC_PREFIX %}
+ {% load static %}
+ {% get_static_prefix as STATIC_PREFIX %}
<img src="{{ STATIC_PREFIX }}images/hi.jpg" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" />
@@ -213,7 +213,7 @@ Thus, the ``staticfiles`` app ships with a quick and dirty helper view that you
can use to serve files locally in development.
This view is automatically enabled and will serve your static files at
-:setting:`STATICFILES_URL` when you use the built-in :djadmin:`runserver`.
+:setting:`STATIC_URL` when you use the built-in :djadmin:`runserver`.
To enable this view if you are using some other server for local development,
you'll add a couple of lines to your URLconf. The first line goes at the top of
@@ -225,11 +225,11 @@ the file, and the last line at the bottom::
urlpatterns += staticfiles_urlpatterns()
-This will inspect your :setting:`STATICFILES_URL` and
-:setting:`STATICFILES_ROOT` settings and wire up the view to serve static media
+This will inspect your :setting:`STATIC_URL` and
+:setting:`STATIC_ROOT` settings and wire up the view to serve static media
accordingly. Don't forget to set the :setting:`STATICFILES_DIRS` setting
appropriately to let ``django.contrib.staticfiles`` know where to look for
-files.
+(additional) files.
.. warning::
@@ -239,6 +239,9 @@ files.
**insecure**. This is only intended for local development, and should
**never be used in production**.
+ Additionally, your :setting:`STATIC_URL` setting can't be either empty
+ or a full URL such as ``http://static.example.com/``.
+
For a few more details, including an alternate method of enabling this view,
see :ref:`staticfiles-development-view`.
@@ -249,7 +252,7 @@ Serving static files in production
The basic outline of putting static files into production is simple: run the
:djadmin:`collectstatic` command when static media changes, then arrange for the
-collected media directory (:setting:`STATICFILES_ROOT`) to be moved to the media
+collected media directory (:setting:`STATIC_ROOT`) to be moved to the media
server and served.
Of course, as with all deployment tasks, the devil's in the details. Every
@@ -264,8 +267,8 @@ app, the basic outline gets modified to look something like:
* Push your code up to the deployment server.
* On the server, run :djadmin:`collectstatic` to move all the media into
- :setting:`STATICFILES_ROOT`.
- * Point your web server at :setting:`STATICFILES_ROOT`. For example, here's
+ :setting:`STATIC_ROOT`.
+ * Point your web server at :setting:`STATIC_ROOT`. For example, here's
:ref:`how to do this under Apache and mod_wsgi <serving-media-files>`.
You'll probably want to automate this process, especially if you've got multiple
@@ -322,7 +325,7 @@ Since your media server won't be running Django, you'll need to modify the
deployment strategy to look something like:
* When your media changes, run :djadmin:`collectstatic` locally.
- * Push your local :setting:`STATICFILES_ROOT` up to the media server
+ * Push your local :setting:`STATIC_ROOT` up to the media server
into the directory that's being served. ``rsync`` is a good
choice for this step since it only needs to transfer the
bits of static media that have changed.
@@ -403,9 +406,6 @@ you'll need to make a few changes:
* The management commands ``build_static`` and ``resolve_static`` are now
called :djadmin:`collectstatic` and :djadmin:`findstatic`.
- * The settings ``STATIC_URL`` and ``STATIC_ROOT`` were renamed to
- :setting:`STATICFILES_URL` and :setting:`STATICFILES_ROOT`.
-
* The settings ``STATICFILES_PREPEND_LABEL_APPS``,
``STATICFILES_MEDIA_DIRNAMES`` and ``STATICFILES_EXCLUDED_APPS`` were
removed.
View
2  docs/man/django-admin.1
@@ -165,7 +165,7 @@ Do not prompt the user for input.
Disable the development server's auto\-reloader.
.TP
.I \-\-nostatic
-Disable automatic serving of static files from STATICFILES_URL.
+Disable automatic serving of static files from STATIC_URL.
.TP
.I \-\-insecure
Enables serving of static files even if DEBUG is False.
View
122 docs/ref/contrib/staticfiles.txt
@@ -23,48 +23,11 @@ Settings
.. highlight:: python
-The following settings control the behavior of the staticfiles app. Only
-:setting:`STATICFILES_ROOT` is required, but you'll probably also need to
-configure :setting:`STATICFILES_URL` as well.
-
-.. setting:: STATICFILES_ROOT
-
-STATICFILES_ROOT
-----------------
-
-Default: ``''`` (Empty string)
-
-The absolute path to the directory that the :djadmin:`collectstatic` management
-command will collect static files into, for serving from
-:setting:`STATICFILES_URL`::
-
- STATICFILES_ROOT = "/home/example.com/static/"
-
-This is a **required setting** unless you've overridden
-:setting:`STATICFILES_STORAGE` and are using a custom storage backend.
-
-This is not a place to store your static files permanently under version
-control; you should do that in directories that will be found by your
-:setting:`STATICFILES_FINDERS` (by default, per-app ``static/`` subdirectories,
-and any directories you include in :setting:`STATICFILES_DIRS`). Files from
-those locations will be collected into :setting:`STATICFILES_ROOT`.
-
-.. setting:: STATICFILES_URL
-
-STATICFILES_URL
----------------
-
-Default: ``'/static/'``
-
-The URL that handles the files served from :setting:`STATICFILES_ROOT`, e.g.::
-
- STATICFILES_URL = '/site_media/static/'
-
-... or perhaps::
-
- STATICFILES_URL = 'http://static.example.com/'
+.. note::
-This should **always** have a trailing slash.
+ The following settings control the behavior of the staticfiles app.
+ Configuring the global settings :setting:`STATIC_ROOT` and
+ :setting:`STATIC_URL` is **required**.
.. setting:: STATICFILES_DIRS
@@ -98,7 +61,7 @@ tuples, e.g.::
With this configuration, the :djadmin:`collectstatic` management command would
for example collect the stats files in a ``'downloads'`` directory. So
-assuming you have :setting:`STATICFILES_URL` set ``'/static/'``, this would
+assuming you have :setting:`STATIC_URL` set ``'/static/'``, this would
allow you to refer to the file ``'/opt/webfiles/stats/polls_20101022.tar.gz'``
with ``'/static/downloads/polls_20101022.tar.gz'`` in your templates.
@@ -153,14 +116,14 @@ Management Commands
.. highlight:: console
-``django.contrib.staticfiles`` exposes two management commands.
+``django.contrib.staticfiles`` exposes three management commands.
collectstatic
-------------
.. django-admin:: collectstatic
-Collects the static files into :setting:`STATICFILES_ROOT`.
+Collects the static files into :setting:`STATIC_ROOT`.
Duplicate file names are by default resolved in a similar way to how template
resolution works: the file that is first found in one of the specified
@@ -218,44 +181,76 @@ for each relative path, use the ``--first`` option::
This is a debugging aid; it'll show you exactly which static file will be
collected for a given path.
+runserver
+---------
+
+Overrides the core :djadmin:`runserver` command if the ``staticfiles`` app
+is :setting:`installed<INSTALLED_APPS>` and adds automatic serving of static
+files and the following new options.
+
+.. django-admin-option:: --nostatic
+
+Use the ``--nostatic`` option to disable serving of static files with the
+:doc:`staticfiles </ref/contrib/staticfiles>` app entirely. This option is
+only available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
+in your project's :setting:`INSTALLED_APPS` setting.
+
+Example usage::
+
+ django-admin.py runserver --nostatic
+
+.. django-admin-option:: --insecure
+
+Use the ``--insecure`` option to force serving of static files with the
+:doc:`staticfiles </ref/contrib/staticfiles>` app even if the :setting:`DEBUG`
+setting is ``False``. By using this you acknowledge the fact that it's
+**grossly inefficient** and probably **insecure**. This is only intended for
+local development, should **never be used in production** and is only
+available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
+in your project's :setting:`INSTALLED_APPS` setting.
+
+Example usage::
+
+ django-admin.py runserver --insecure
+
.. currentmodule:: None
Other Helpers
=============
-The ``staticfiles`` context processor
--------------------------------------
+The ``static`` context processor
+--------------------------------
-.. function:: django.contrib.staticfiles.context_processors.staticfiles
+.. function:: django.core.context_processors.static
-This context processor adds the :setting:`STATICFILES_URL` into each template
-context as the variable ``{{ STATICFILES_URL }}``. To use it, make sure that
-``'django.contrib.staticfiles.context_processors.staticfiles'`` appears
-somewhere in your :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting.
+This context processor adds the :setting:`STATIC_URL` into each template
+context as the variable ``{{ STATIC_URL }}``. To use it, make sure that
+``'django.core.context_processors.static'`` appears somewhere in your
+:setting:`TEMPLATE_CONTEXT_PROCESSORS` setting.
Remember, only templates rendered with :class:`~django.template.RequestContext`
will have acces to the data provided by this (and any) context processor.
-.. templatetag:: get_staticfiles_prefix
+.. templatetag:: get_static_prefix
-The ``get_staticfiles_prefix`` templatetag
-==========================================
+The ``get_static_prefix`` templatetag
+=====================================
.. highlight:: html+django
If you're not using :class:`~django.template.RequestContext`, or if you need
-more control over exactly where and how :setting:`STATICFILES_URL` is injected
-into the template, you can use the :ttag:`get_staticfiles_prefix` template tag
+more control over exactly where and how :setting:`STATIC_URL` is injected
+into the template, you can use the :ttag:`get_static_prefix` template tag
instead::
- {% load staticfiles %}
- <img src="{% get_staticfiles_prefix %}images/hi.jpg" />
+ {% load static %}
+ <img src="{% get_static_prefix %}images/hi.jpg" />
There's also a second form you can use to avoid extra processing if you need
the value multiple times::
- {% load staticfiles %}
- {% get_staticfiles_prefix as STATIC_PREFIX %}
+ {% load static %}
+ {% get_static_prefix as STATIC_PREFIX %}
<img src="{{ STATIC_PREFIX }}images/hi.jpg" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" />
@@ -292,7 +287,7 @@ primary URL configuration::
)
Note, the begin of the pattern (``r'^static/'``) should be your
-:setting:`STATICFILES_URL` setting.
+:setting:`STATIC_URL` setting.
Since this is a bit finicky, there's also a helper function that'll do this for you:
@@ -307,3 +302,8 @@ already defined pattern list. Use it like this::
urlpatterns += staticfiles_urlpatterns()
+.. warning::
+
+ This helper function will only work if :setting:`DEBUG` is ``True``
+ and your :setting:`STATIC_URL` setting is neither empty nor a full
+ URL such as ``http://static.example.com/``.
View
29 docs/ref/django-admin.txt
@@ -681,35 +681,6 @@ Example usage::
django-admin.py runserver --noreload
-.. django-admin-option:: --nostatic
-
-Use the ``--nostatic`` option to disable serving of static files with the
-:doc:`staticfiles </ref/contrib/staticfiles>` app entirely. This option is
-only available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
-in your project's :setting:`INSTALLED_APPS` setting.
-
-Example usage::
-
- django-admin.py runserver --nostatic
-
-.. django-admin-option:: --insecure
-
-Use the ``--insecure`` option to force serving of static files with the
-:doc:`staticfiles </ref/contrib/staticfiles>` app even if the :setting:`DEBUG`
-setting is ``False``. By using this you acknowledge the fact that it's
-**grossly inefficient** and probably **insecure**. This is only intended for
-local development, should **never be used in production** and is only
-available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
-in your project's :setting:`INSTALLED_APPS` setting.
-
-See the :doc:`reference documentation of the app </ref/contrib/staticfiles>`
-for more details and learn how to :doc:`manage and deploy static files
-</howto/static-files>` correctly.
-
-Example usage::
-
- django-admin.py runserver --insecure
-
Examples of using different ports and addresses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
View
60 docs/ref/settings.txt
@@ -53,10 +53,10 @@ Default: ``'/static/admin/'``
The URL prefix for admin media -- CSS, JavaScript and images used by the Django
administrative interface. Make sure to use a trailing slash, and to have this be
-different from the :setting:``MEDIA_URL`` setting (since the same URL cannot be
+different from the :setting:`MEDIA_URL` setting (since the same URL cannot be
mapped onto two different sets of files). For integration with :doc:`staticfiles
</ref/contrib/staticfiles>`, this should be the same as
-:setting:`STATICFILES_URL` followed by ``'admin/'``.
+:setting:`STATIC_URL` followed by ``'admin/'``.
.. setting:: ADMINS
@@ -1122,12 +1122,12 @@ Default: ``''`` (Empty string)
URL that handles the media served from :setting:`MEDIA_ROOT`, used
for :doc:`managing stored files </topics/files>`.
-Example: ``"http://media.lawrence.com"``
+Example: ``"http://media.lawrence.com/"``
Note that this should have a trailing slash if it has a path component.
- * Good: ``"http://www.example.com/static/"``
- * Bad: ``"http://www.example.com/static"``
+ * Good: ``"http://www.example.com/media/"``
+ * Bad: ``"http://www.example.com/media"``
MESSAGE_LEVEL
-------------
@@ -1486,6 +1486,49 @@ See :doc:`/ref/contrib/sites`.
.. _site framework docs: ../sites/
+.. setting:: STATIC_ROOT
+
+STATIC_ROOT
+-----------
+
+Default: ``''`` (Empty string)
+
+The absolute path to the directory that contains static content.
+
+Example: ``"/home/example.com/static/"``
+
+When using the :djadmin:`collectstatic` management command of the optional,
+:doc:`staticfiles</ref/contrib/staticfiles>` app this will be used to collect
+static files into and served from :setting:`STATIC_URL`.
+
+In that case this is a **required setting**, unless you've overridden
+:setting:`STATICFILES_STORAGE` and are using a custom storage backend.
+
+This is not a place to store your static files permanently under version
+control; you should do that in directories that will be found by your
+:setting:`STATICFILES_FINDERS` (by default, per-app ``static/`` subdirectories,
+and any directories you include in :setting:`STATICFILES_DIRS`). Files from
+those locations will be collected into :setting:`STATIC_ROOT`.
+
+See :doc:`/ref/contrib/staticfiles` and :setting:`STATIC_URL`.
+
+.. setting:: STATIC_URL
+
+STATIC_URL
+----------
+
+Default: ``None``
+
+URL that handles the files served from :setting:`STATIC_ROOT`.
+
+Example: ``"/site_media/static/"`` or ``"http://static.example.com/"``
+
+If not ``None``, this will be used as the base path for
+:ref:`media definitions<form-media-paths>` and the
+:doc:`staticfiles app</ref/contrib/staticfiles>`.
+
+See :setting:`STATIC_ROOT`.
+
.. setting:: TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS
@@ -1496,7 +1539,8 @@ Default::
("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
- "django.contrib.staticfiles.context_processors.staticfiles",
+ "django.core.context_processors.media",
+ "django.core.context_processors.static",
"django.contrib.messages.context_processors.messages")
A tuple of callables that are used to populate the context in ``RequestContext``.
@@ -1513,6 +1557,10 @@ of items to be merged into the context.
``django.core.context_processors.auth`` to
``django.contrib.auth.context_processors.auth``.
+.. versionadded:: 1.3
+ The ``django.core.context_processors.static`` context processor
+ was added in this release.
+
.. setting:: TEMPLATE_DEBUG
TEMPLATE_DEBUG
View
13 docs/ref/templates/api.txt
@@ -312,8 +312,8 @@ and return a dictionary of items to be merged into the context. By default,
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
- "django.contrib.messages.context_processors.messages",
- "django.contrib.staticfiles.context_processors.staticfiles")
+ "django.core.context_processors.static",
+ "django.contrib.messages.context_processors.messages")
.. versionadded:: 1.2
In addition to these, ``RequestContext`` always uses
@@ -435,6 +435,15 @@ If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every
``RequestContext`` will contain a variable ``MEDIA_URL``, providing the
value of the :setting:`MEDIA_URL` setting.
+django.core.context_processors.static
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 1.3
+
+If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every
+``RequestContext`` will contain a variable ``STATIC_URL``, providing the
+value of the :setting:`STATIC_URL` setting.
+
django.core.context_processors.csrf
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
View
6 docs/releases/1.3-alpha-1.txt
@@ -21,7 +21,7 @@ changes`_ and an easy upgrade path from Django 1.2.
.. _new features: `What's new in Django 1.3 alpha 1`_
-.. _backwards incompatible changes: backwards-incompatible-changes-1.3_
+.. _backwards incompatible changes: backwards-incompatible-changes-1.3-alpha-1_
What's new in Django 1.3 alpha 1
================================
@@ -161,7 +161,7 @@ requests. These include:
easier to test the database activity associated with a view.
-.. _backwards-incompatible-changes-1.3:
+.. _backwards-incompatible-changes-1.3-alpha-1:
Backwards-incompatible changes in 1.3 alpha 1
=============================================
@@ -270,8 +270,6 @@ local flavors:
official designation "Aceh (ACE)".
-.. _deprecated-features-1.3:
-
Features deprecated in 1.3
==========================
View
45 docs/releases/1.3-alpha-2.txt
@@ -13,10 +13,6 @@ prior to the final 1.3 release.
As such, this release is *not* intended for production use, and any such use
is discouraged.
-.. _new features: `What's new in Django 1.3 alpha 2`_
-
-.. _backwards incompatible changes: backwards-incompatible-changes-1.3-alpha-2_
-
What's new in Django 1.3 alpha 2
================================
@@ -43,6 +39,47 @@ See the :doc:`reference documentation of the app </ref/contrib/staticfiles>`
for more details or learn how to :doc:`manage static files
</howto/static-files>`.
+Backwards-incompatible changes in 1.3 alpha 2
+=============================================
+
+Introduction of STATIC_URL and STATIC_ROOT settings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The newly introduced :doc:`/ref/contrib/staticfiles` app extends Django's
+abilities to handle static app and project files, required the additon of
+settings to refer to those files in templates and code, especially in
+contrast to the :setting:`MEDIA_URL` and :setting:`MEDIA_ROOT` settings that
+refer to user-uploaded files.
+
+Prior to 1.3 alpha 2 these settings were called ``STATICFILES_URL`` and
+``STATICFILES_ROOT`` to follow the naming scheme for app centric settings.
+Based on feedback from the community it became apparent that those settings
+created confusion, especially given the fact handling static files is also
+desired outside the use of the optional ``staticfiles`` app.
+
+As a result, we take the followig steps to rectify the issue:
+
+ * Two new global settings that will be used by -- **but are not limited
+ to** -- the :doc:`staticfiles</ref/contrib/staticfiles>` app:
+
+ * :setting:`STATIC_ROOT` (formally ``STATICFILES_ROOT``)
+
+ * :setting:`STATIC_URL` (formally ``STATICFILES_URL``)
+
+ * Moving the
+ ``django.contrib.staticfiles.templatetags.staticfiles.get_staticfiles_prefix``
+ template tag to the core (``django.templatetags.static``) and renaming
+ it to :ttag:`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
+ :func:`~django.core.context_processors.static`.
+
+ * :ref:`form-media-paths` will use :setting:`STATIC_URL` as the prefix
+ **if the value is not None**, and falls back to the previously used
+ :setting:`MEDIA_URL`.
+
The Django 1.3 roadmap
======================
View
2  docs/releases/1.3.txt
@@ -59,7 +59,7 @@ In previous versions of Django, it was common to place static assets in
app is to make it easier to keep static files separate from user-uploaded
files. For this reason, you will probably want to make your
:setting:`MEDIA_ROOT` and :setting:`MEDIA_URL` different from your
-:setting:`STATICFILES_ROOT` and :setting:`STATICFILES_URL`. You will need to
+:setting:`STATIC_ROOT` and :setting:`STATIC_URL`. You will need to
arrange for serving of files in :setting:`MEDIA_ROOT` yourself;
``staticfiles`` does not deal with user-uploaded media at all.
View
1  docs/releases/index.txt
@@ -64,6 +64,7 @@ notes.
.. toctree::
:maxdepth: 1
+ 1.3-alpha-2
1.3-alpha-1
1.2-rc-1
1.2-beta-1
View
41 docs/topics/forms/media.txt
@@ -190,28 +190,51 @@ also be defined in a dynamic fashion::
See the section on `Media objects`_ for more details on how to construct
return values for dynamic media properties.
+.. _form-media-paths:
+
Paths in media definitions
--------------------------
+.. versionchanged:: 1.3
+
Paths used to specify media can be either relative or absolute. If a path
starts with '/', 'http://' or 'https://', it will be interpreted as an absolute
path, and left as-is. All other paths will be prepended with the value of
-``settings.MEDIA_URL``. For example, if the MEDIA_URL for your site was
-``http://media.example.com/``::
+the appropriate prefix.
+
+As part of the introduction of the
+:doc:`staticfiles app </ref/contrib/staticfiles>` two new settings were added
+to refer to "static content" (images, CSS, Javascript, etc.) that are needed
+to render a complete web page: :setting:`STATIC_URL` and :setting:`STATIC_ROOT`.
+
+To find the appropriate prefix to use, Django will check if the
+:setting:`STATIC_URL` setting is not ``None`` and automatically fall back
+to using :setting:`MEDIA_URL`. For example, if the :setting:`MEDIA_URL` for
+your site was ``'http://uploads.example.com/'`` and :setting:`STATIC_URL`
+was ``None``::
+
+ >>> class CalendarWidget(forms.TextInput):
+ class Media:
+ css = {
+ 'all': ('/css/pretty.css',),
+ }
+ js = ('animations.js', 'http://othersite.com/actions.js')
- class CalendarWidget(forms.TextInput):
- class Media:
- css = {
- 'all': ('/css/pretty.css',),
- }
- js = ('animations.js', 'http://othersite.com/actions.js')
+ >>> w = CalendarWidget()
+ >>> print w.media
+ <link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
+ <script type="text/javascript" src="http://uploads.example.com/animations.js"></script>
+ <script type="text/javascript" src="http://othersite.com/actions.js"></script>
+
+But if :setting:`STATIC_URL` is ``'http://static.example.com/'``::
>>> w = CalendarWidget()
>>> print w.media
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
- <script type="text/javascript" src="http://media.example.com/animations.js"></script>
+ <script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://othersite.com/actions.js"></script>
+
Media objects
-------------
View
460 tests/regressiontests/forms/tests/media.py
@@ -458,3 +458,463 @@ class Media:
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />""")
+
+
+class StaticFormsMediaTestCase(TestCase):
+ # Tests for the media handling on widgets and forms
+ def setUp(self):
+ super(StaticFormsMediaTestCase, self).setUp()
+ self.original_media_url = settings.MEDIA_URL
+ self.original_static_url = settings.STATIC_URL
+ settings.MEDIA_URL = 'http://media.example.com/static/'
+ settings.STATIC_URL = 'http://media.example.com/static/'
+
+ def tearDown(self):
+ settings.MEDIA_URL = self.original_media_url
+ settings.STATIC_URL = self.original_static_url
+ super(StaticFormsMediaTestCase, self).tearDown()
+
+ def test_construction(self):
+ # Check construction of media objects
+ m = Media(css={'all': ('path/to/css1','/path/to/css2')}, js=('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3'))
+ self.assertEqual(str(m), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
+
+ class Foo:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ m3 = Media(Foo)
+ self.assertEqual(str(m3), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
+
+ # A widget can exist without a media definition
+ class MyWidget(TextInput):
+ pass
+
+ w = MyWidget()
+ self.assertEqual(str(w.media), '')
+
+ def test_media_dsl(self):
+ ###############################################################
+ # DSL Class-based media definitions
+ ###############################################################
+
+ # A widget can define media if it needs to.
+ # Any absolute path will be preserved; relative paths are combined
+ # with the value of settings.MEDIA_URL
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ w1 = MyWidget1()
+ self.assertEqual(str(w1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
+
+ # Media objects can be interrogated by media type
+ self.assertEqual(str(w1.media['css']), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />""")
+
+ self.assertEqual(str(w1.media['js']), """<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
+
+ def test_combine_media(self):
+ # Media objects can be combined. Any given media resource will appear only
+ # once. Duplicated media definitions are ignored.
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ class MyWidget2(TextInput):
+ class Media:
+ css = {
+ 'all': ('/path/to/css2','/path/to/css3')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ class MyWidget3(TextInput):
+ class Media:
+ css = {
+ 'all': ('/path/to/css3','path/to/css1')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ w1 = MyWidget1()
+ w2 = MyWidget2()
+ w3 = MyWidget3()
+ self.assertEqual(str(w1.media + w2.media + w3.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ # Check that media addition hasn't affected the original objects
+ self.assertEqual(str(w1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
+
+ # Regression check for #12879: specifying the same CSS or JS file
+ # multiple times in a single Media instance should result in that file
+ # only being included once.
+ class MyWidget4(TextInput):
+ class Media:
+ css = {'all': ('/path/to/css1', '/path/to/css1')}
+ js = ('/path/to/js1', '/path/to/js1')
+
+ w4 = MyWidget4()
+ self.assertEqual(str(w4.media), """<link href="/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>""")
+
+ def test_media_property(self):
+ ###############################################################
+ # Property-based media definitions
+ ###############################################################
+
+ # Widget media can be defined as a property
+ class MyWidget4(TextInput):
+ def _media(self):
+ return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
+ media = property(_media)
+
+ w4 = MyWidget4()
+ self.assertEqual(str(w4.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/some/js"></script>""")
+
+ # Media properties can reference the media of their parents
+ class MyWidget5(MyWidget4):
+ def _media(self):
+ return super(MyWidget5, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
+ media = property(_media)
+
+ w5 = MyWidget5()
+ self.assertEqual(str(w5.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
+<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/some/js"></script>
+<script type="text/javascript" src="/other/js"></script>""")
+
+ def test_media_property_parent_references(self):
+ # Media properties can reference the media of their parents,
+ # even if the parent media was defined using a class
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ class MyWidget6(MyWidget1):
+ def _media(self):
+ return super(MyWidget6, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
+ media = property(_media)
+
+ w6 = MyWidget6()
+ self.assertEqual(str(w6.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/other/js"></script>""")
+
+ def test_media_inheritance(self):
+ ###############################################################
+ # Inheritance of media
+ ###############################################################
+
+ # If a widget extends another but provides no media definition, it inherits the parent widget's media
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ class MyWidget7(MyWidget1):
+ pass
+
+ w7 = MyWidget7()
+ self.assertEqual(str(w7.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
+
+ # If a widget extends another but defines media, it extends the parent widget's media by default
+ class MyWidget8(MyWidget1):
+ class Media:
+ css = {
+ 'all': ('/path/to/css3','path/to/css1')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ w8 = MyWidget8()
+ self.assertEqual(str(w8.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ def test_media_inheritance_from_property(self):
+ # If a widget extends another but defines media, it extends the parents widget's media,
+ # even if the parent defined media using a property.
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ class MyWidget4(TextInput):
+ def _media(self):
+ return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
+ media = property(_media)
+
+ class MyWidget9(MyWidget4):
+ class Media:
+ css = {
+ 'all': ('/other/path',)
+ }
+ js = ('/other/js',)
+
+ w9 = MyWidget9()
+ self.assertEqual(str(w9.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
+<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/some/js"></script>
+<script type="text/javascript" src="/other/js"></script>""")
+
+ # A widget can disable media inheritance by specifying 'extend=False'
+ class MyWidget10(MyWidget1):
+ class Media:
+ extend = False
+ css = {
+ 'all': ('/path/to/css3','path/to/css1')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ w10 = MyWidget10()
+ self.assertEqual(str(w10.media), """<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ def test_media_inheritance_extends(self):
+ # A widget can explicitly enable full media inheritance by specifying 'extend=True'
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ class MyWidget11(MyWidget1):
+ class Media:
+ extend = True
+ css = {
+ 'all': ('/path/to/css3','path/to/css1')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ w11 = MyWidget11()
+ self.assertEqual(str(w11.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ def test_media_inheritance_single_type(self):
+ # A widget can enable inheritance of one media type by specifying extend as a tuple
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ class MyWidget12(MyWidget1):
+ class Media:
+ extend = ('css',)
+ css = {
+ 'all': ('/path/to/css3','path/to/css1')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ w12 = MyWidget12()
+ self.assertEqual(str(w12.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ def test_multi_media(self):
+ ###############################################################
+ # Multi-media handling for CSS
+ ###############################################################
+
+ # A widget can define CSS media for multiple output media types
+ class MultimediaWidget(TextInput):
+ class Media:
+ css = {
+ 'screen, print': ('/file1','/file2'),
+ 'screen': ('/file3',),
+ 'print': ('/file4',)
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ multimedia = MultimediaWidget()
+ self.assertEqual(str(multimedia.media), """<link href="/file4" type="text/css" media="print" rel="stylesheet" />
+<link href="/file3" type="text/css" media="screen" rel="stylesheet" />
+<link href="/file1" type="text/css" media="screen, print" rel="stylesheet" />
+<link href="/file2" type="text/css" media="screen, print" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ def test_multi_widget(self):
+ ###############################################################
+ # Multiwidget media handling
+ ###############################################################
+
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ class MyWidget2(TextInput):
+ class Media:
+ css = {
+ 'all': ('/path/to/css2','/path/to/css3')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ class MyWidget3(TextInput):
+ class Media:
+ css = {
+ 'all': ('/path/to/css3','path/to/css1')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ # MultiWidgets have a default media definition that gets all the
+ # media from the component widgets
+ class MyMultiWidget(MultiWidget):
+ def __init__(self, attrs=None):
+ widgets = [MyWidget1, MyWidget2, MyWidget3]
+ super(MyMultiWidget, self).__init__(widgets, attrs)
+
+ mymulti = MyMultiWidget()
+ self.assertEqual(str(mymulti.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ def test_form_media(self):
+ ###############################################################
+ # Media processing for forms
+ ###############################################################
+
+ class MyWidget1(TextInput):
+ class Media:
+ css = {
+ 'all': ('path/to/css1','/path/to/css2')
+ }
+ js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
+
+ class MyWidget2(TextInput):
+ class Media:
+ css = {
+ 'all': ('/path/to/css2','/path/to/css3')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ class MyWidget3(TextInput):
+ class Media:
+ css = {
+ 'all': ('/path/to/css3','path/to/css1')
+ }
+ js = ('/path/to/js1','/path/to/js4')
+
+ # You can ask a form for the media required by its widgets.
+ class MyForm(Form):
+ field1 = CharField(max_length=20, widget=MyWidget1())
+ field2 = CharField(max_length=20, widget=MyWidget2())
+ f1 = MyForm()
+ self.assertEqual(str(f1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ # Form media can be combined to produce a single media definition.
+ class AnotherForm(Form):
+ field3 = CharField(max_length=20, widget=MyWidget3())
+ f2 = AnotherForm()
+ self.assertEqual(str(f1.media + f2.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/path/to/js4"></script>""")
+
+ # Forms can also define media, following the same rules as widgets.
+ class FormWithMedia(Form):
+ field1 = CharField(max_length=20, widget=MyWidget1())
+ field2 = CharField(max_length=20, widget=MyWidget2())
+ class Media:
+ js = ('/some/form/javascript',)
+ css = {
+ 'all': ('/some/form/css',)
+ }
+ f3 = FormWithMedia()
+ self.assertEqual(str(f3.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
+<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/path/to/js4"></script>
+<script type="text/javascript" src="/some/form/javascript"></script>""")
+
+ # Media works in templates
+ from django.template import Template, Context
+ self.assertEqual(Template("{{ form.media.js }}{{ form.media.css }}").render(Context({'form': f3})), """<script type="text/javascript" src="/path/to/js1"></script>
+<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
+<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
+<script type="text/javascript" src="/path/to/js4"></script>
+<script type="text/javascript" src="/some/form/javascript"></script><link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
+<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
+<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />""")
+
View
50 tests/regressiontests/staticfiles_tests/tests.py
@@ -23,8 +23,8 @@ class StaticFilesTestCase(TestCase):
Test case with a couple utility assertions.
"""
def setUp(self):
- self.old_staticfiles_url = settings.STATICFILES_URL
- self.old_staticfiles_root = settings.STATICFILES_ROOT
+ self.old_static_url = settings.STATIC_URL
+ self.old_static_root = settings.STATIC_ROOT
self.old_staticfiles_dirs = settings.STATICFILES_DIRS
self.old_staticfiles_finders = settings.STATICFILES_FINDERS
self.old_media_root = settings.MEDIA_ROOT
@@ -40,8 +40,8 @@ def setUp(self):
settings.DEBUG = True
settings.MEDIA_ROOT = os.path.join(site_media, 'media')
settings.MEDIA_URL = '/media/'
- settings.STATICFILES_ROOT = os.path.join(site_media, 'static')
- settings.STATICFILES_URL = '/static/'
+ settings.STATIC_ROOT = os.path.join(site_media, 'static')
+ settings.STATIC_URL = '/static/'
settings.ADMIN_MEDIA_PREFIX = '/static/admin/'
settings.STATICFILES_DIRS = (
os.path.join(TEST_ROOT, 'project', 'documents'),
@@ -52,6 +52,7 @@ def setUp(self):
'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
settings.INSTALLED_APPS = [
+ "django.contrib.staticfiles",
"regressiontests.staticfiles_tests",
]
@@ -65,8 +66,8 @@ def tearDown(self):
settings.MEDIA_ROOT = self.old_media_root
settings.MEDIA_URL = self.old_media_url
settings.ADMIN_MEDIA_PREFIX = self.old_admin_media_prefix
- settings.STATICFILES_ROOT = self.old_staticfiles_root
- settings.STATICFILES_URL = self.old_staticfiles_url
+ settings.STATIC_ROOT = self.old_static_root
+ settings.STATIC_URL = self.old_static_url
settings.STATICFILES_DIRS = self.old_staticfiles_dirs
settings.STATICFILES_FINDERS = self.old_staticfiles_finders
settings.INSTALLED_APPS = self.old_installed_apps
@@ -91,13 +92,13 @@ class BuildStaticTestCase(StaticFilesTestCase):
def setUp(self):
super(BuildStaticTestCase, self).setUp()
self.old_staticfiles_storage = settings.STATICFILES_STORAGE
- self.old_root = settings.STATICFILES_ROOT
- settings.STATICFILES_ROOT = tempfile.mkdtemp()
+ self.old_root = settings.STATIC_ROOT
+ settings.STATIC_ROOT = tempfile.mkdtemp()
self.run_collectstatic()
def tearDown(self):
- shutil.rmtree(settings.STATICFILES_ROOT)
- settings.STATICFILES_ROOT = self.old_root
+ shutil.rmtree(settings.STATIC_ROOT)
+ settings.STATIC_ROOT = self.old_root
super(BuildStaticTestCase, self).tearDown()
def run_collectstatic(self, **kwargs):
@@ -106,7 +107,7 @@ def run_collectstatic(self, **kwargs):
def _get_file(self, filepath):
assert filepath, 'filepath is empty.'
- filepath = os.path.join(settings.STATICFILES_ROOT, filepath)
+ filepath = os.path.join(settings.STATIC_ROOT, filepath)
f = open(filepath)
try:
return f.read()
@@ -231,7 +232,7 @@ def test_no_files_created(self):
"""
With --dry-run, no files created in destination dir.
"""
- self.assertEquals(os.listdir(settings.STATICFILES_ROOT), [])
+ self.assertEquals(os.listdir(settings.STATIC_ROOT), [])
if sys.platform != 'win32':
@@ -251,7 +252,7 @@ def test_links_created(self):
With ``--link``, symbolic links are created.
"""
- self.failUnless(os.path.islink(os.path.join(settings.STATICFILES_ROOT, 'test.txt')))
+ self.failUnless(os.path.islink(os.path.join(settings.STATIC_ROOT, 'test.txt')))
class TestServeStatic(StaticFilesTestCase):
@@ -262,7 +263,7 @@ class TestServeStatic(StaticFilesTestCase):
def _response(self, filepath):
return self.client.get(
- posixpath.join(settings.STATICFILES_URL, filepath))
+ posixpath.join(settings.STATIC_URL, filepath))
def assertFileContains(self, filepath, text):
self.assertContains(self._response(filepath), text)
@@ -372,24 +373,3 @@ def test_get_finder(self):
finders.get_finder, "django.contrib.staticfiles.finders.FooBarFinder")
self.assertRaises(ImproperlyConfigured,
finders.get_finder, "foo.bar.FooBarFinder")
-
-
-class TemplateTagTest(TestCase):
- def test_get_staticfiles_prefix(self):
- """
- Test the get_staticfiles_prefix helper return the STATICFILES_URL setting.
- """
- self.assertEquals(Template(
- "{% load staticfiles %}"
- "{% get_staticfiles_prefix %}"
- ).render(Context()), settings.STATICFILES_URL)
-
- def test_get_staticfiles_prefix_with_as(self):
- """
- Test the get_staticfiles_prefix helper return the STATICFILES_URL setting.
- """
- self.assertEquals(Template(
- "{% load staticfiles %}"
- "{% get_staticfiles_prefix as staticfiles_prefix %}"
- "{{ staticfiles_prefix }}"
- ).render(Context()), settings.STATICFILES_URL)
View
26 tests/regressiontests/templates/tests.py
@@ -114,6 +114,16 @@ def __str__(self):
return u'ŠĐĆŽćžšđ'.encode('utf-8')
class Templates(unittest.TestCase):
+ def setUp(self):
+ self.old_static_url = settings.STATIC_URL
+ self.old_media_url = settings.MEDIA_URL
+ settings.STATIC_URL = u"/static/"
+ settings.MEDIA_URL = u"/media/"
+
+ def tearDown(self):
+ settings.STATIC_URL = self.old_static_url
+ settings.MEDIA_URL = self.old_media_url
+
def test_loaders_security(self):
ad_loader = app_directories.Loader()
fs_loader = filesystem.Loader()
@@ -1328,24 +1338,28 @@ def get_template_tests(self):
'autoescape-filtertag01': ("{{ first }}{% filter safe %}{{ first }} x<y{% endfilter %}", {"first": "<a>"}, template.TemplateSyntaxError),
# ifqeual compares unescaped vales.
- 'autoescape-ifequal01': ('{% ifequal var "this & that" %}yes{% endifequal %}', { "var": "this & that" }, "yes" ),
+ 'autoescape-ifequal01': ('{% ifequal var "this & that" %}yes{% endifequal %}', { "var": "this & that" }, "yes"),
# Arguments to filters are 'safe' and manipulate their input unescaped.
'autoescape-filters01': ('{{ var|cut:"&" }}', { "var": "this & that" }, "this that" ),
- 'autoescape-filters02': ('{{ var|join:" & \" }}', { "var": ("Tom", "Dick", "Harry") }, "Tom & Dick & Harry" ),
+ 'autoescape-filters02': ('{{ var|join:" & \" }}', { "var": ("Tom", "Dick", "Harry") }, "Tom & Dick & Harry"),
# Literal strings are safe.
- 'autoescape-literals01': ('{{ "this & that" }}',{}, "this & that" ),
+ 'autoescape-literals01': ('{{ "this & that" }}',{}, "this & that"),
# Iterating over strings outputs safe characters.
- 'autoescape-stringiterations01': ('{% for l in var %}{{ l }},{% endfor %}', {'var': 'K&R'}, "K,&amp;,R," ),
+ 'autoescape-stringiterations01': ('{% for l in var %}{{ l }},{% endfor %}', {'var': 'K&R'}, "K,&amp;,R,"),
# Escape requirement survives lookup.
- 'autoescape-lookup01': ('{{ var.key }}', { "var": {"key": "this & that" }}, "this &amp; that" ),
+ 'autoescape-lookup01': ('{{ var.key }}', { "var": {"key": "this & that" }}, "this &amp; that"),
+ # Static template tags
+ 'static-prefixtag01': ('{% load static %}{% get_static_prefix %}', {}, settings.STATIC_URL),
+ 'static-prefixtag02': ('{% load static %}{% get_static_prefix as static_prefix %}{{ static_prefix }}', {}, settings.STATIC_URL),
+ 'static-prefixtag03': ('{% load static %}{% get_media_prefix %}', {}, settings.MEDIA_URL),
+ 'static-prefixtag04': ('{% load static %}{% get_media_prefix as media_prefix %}{{ media_prefix }}', {}, settings.MEDIA_URL),
}
-
class TemplateTagLoading(unittest.TestCase):
def setUp(self):
Please sign in to comment.
Something went wrong with that request. Please try again.