Fixed #6218 -- Made MEDIA_URL and STATIC_URL require a trailing slash to ensure there is a consistent way to combine paths in templates. Thanks to Michael Toomim, Chris Heisel and Chris Beaven.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@15130 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
7a89d3d503
commit
544ab30ed7
|
@ -9,6 +9,7 @@ a list of all possible variables.
|
|||
import os
|
||||
import re
|
||||
import time # Needed for Windows
|
||||
import warnings
|
||||
|
||||
from django.conf import global_settings
|
||||
from django.utils.functional import LazyObject
|
||||
|
@ -60,7 +61,19 @@ class LazySettings(LazyObject):
|
|||
return bool(self._wrapped)
|
||||
configured = property(configured)
|
||||
|
||||
class Settings(object):
|
||||
|
||||
class BaseSettings(object):
|
||||
"""
|
||||
Common logic for settings whether set by a module or by the user.
|
||||
"""
|
||||
def __setattr__(self, name, value):
|
||||
if name in ("MEDIA_URL", "STATIC_URL") and value and not value.endswith('/'):
|
||||
warnings.warn('If set, %s must end with a slash' % name,
|
||||
PendingDeprecationWarning)
|
||||
object.__setattr__(self, name, value)
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
def __init__(self, settings_module):
|
||||
# update this dict from global settings (but only for ALL_CAPS settings)
|
||||
for setting in dir(global_settings):
|
||||
|
@ -125,7 +138,8 @@ class Settings(object):
|
|||
# ... then invoke it with the logging settings
|
||||
logging_config_func(self.LOGGING)
|
||||
|
||||
class UserSettingsHolder(object):
|
||||
|
||||
class UserSettingsHolder(BaseSettings):
|
||||
"""
|
||||
Holder for user configured settings.
|
||||
"""
|
||||
|
|
|
@ -48,7 +48,7 @@ USE_L10N = True
|
|||
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).
|
||||
# trailing slash.
|
||||
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
|
||||
MEDIA_URL = ''
|
||||
|
||||
|
|
|
@ -101,6 +101,10 @@ their deprecation, as per the :ref:`Django deprecation policy
|
|||
* Authentication backends need to define the boolean attribute
|
||||
``supports_inactive_user``.
|
||||
|
||||
* The ``MEDIA_URL`` or ``STATIC_URL`` settings are required to end
|
||||
with a trailing slash to ensure there is a consistent way to
|
||||
combine paths in templates.
|
||||
|
||||
* 1.5
|
||||
* The ``mod_python`` request handler has been deprecated since the 1.3
|
||||
release. The ``mod_wsgi`` handler should be used instead.
|
||||
|
|
|
@ -1251,10 +1251,8 @@ for :doc:`managing stored files </topics/files>`.
|
|||
|
||||
Example: ``"http://media.lawrence.com/"``
|
||||
|
||||
Note that this should have a trailing slash if it has a path component.
|
||||
|
||||
* Good: ``"http://www.example.com/media/"``
|
||||
* Bad: ``"http://www.example.com/media"``
|
||||
.. versionchanged:: 1.3
|
||||
It must end in a slash if set to a non-empty value.
|
||||
|
||||
MESSAGE_LEVEL
|
||||
-------------
|
||||
|
@ -1664,6 +1662,8 @@ 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>`.
|
||||
|
||||
It must end in a slash if set to a non-empty value.
|
||||
|
||||
See :setting:`STATIC_ROOT`.
|
||||
|
||||
.. setting:: TEMPLATE_CONTEXT_PROCESSORS
|
||||
|
|
|
@ -192,6 +192,22 @@ The GeoDjango test suite is now included when
|
|||
:ref:`running the Django test suite <running-unit-tests>` with ``runtests.py``
|
||||
when using :ref:`spatial database backends <spatial-backends>`.
|
||||
|
||||
``MEDIA_URL`` and ``STATIC_URL`` must end in a slash
|
||||
----------------------------------------------------
|
||||
|
||||
Previously, the ``MEDIA_URL`` setting only required a trailing slash if it
|
||||
contained a suffix beyond the domain name.
|
||||
|
||||
A trailing slash is now *required* for ``MEDIA_URL`` and the new
|
||||
``STATIC_URL`` setting as long as it is not blank. This ensures there is
|
||||
a consistent way to combine paths in templates.
|
||||
|
||||
Project settings which provide either of both settings without a trailing
|
||||
slash will now raise a ``PendingDeprecation`` warning.
|
||||
|
||||
In Django 1.4 this same condition will raise an ``ImproperlyConfigured``
|
||||
exception.
|
||||
|
||||
Everything else
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django.utils import unittest
|
||||
from django.conf import settings, UserSettingsHolder, global_settings
|
||||
|
||||
|
||||
class SettingsTests(unittest.TestCase):
|
||||
|
||||
|
@ -15,3 +17,62 @@ class SettingsTests(unittest.TestCase):
|
|||
|
||||
def test_settings_delete_wrapped(self):
|
||||
self.assertRaises(TypeError, delattr, settings, '_wrapped')
|
||||
|
||||
|
||||
class TrailingSlashURLTests(unittest.TestCase):
|
||||
settings_module = settings
|
||||
|
||||
def setUp(self):
|
||||
self._original_media_url = self.settings_module.MEDIA_URL
|
||||
|
||||
def tearDown(self):
|
||||
self.settings_module.MEDIA_URL = self._original_media_url
|
||||
|
||||
def test_blank(self):
|
||||
"""
|
||||
If blank, no PendingDeprecationWarning error will be raised, even though it
|
||||
doesn't end in a slash.
|
||||
"""
|
||||
self.settings_module.MEDIA_URL = ''
|
||||
self.assertEqual('', self.settings_module.MEDIA_URL)
|
||||
|
||||
def test_end_slash(self):
|
||||
"""
|
||||
MEDIA_URL works if you end in a slash.
|
||||
"""
|
||||
self.settings_module.MEDIA_URL = '/foo/'
|
||||
self.assertEqual('/foo/', self.settings_module.MEDIA_URL)
|
||||
|
||||
self.settings_module.MEDIA_URL = 'http://media.foo.com/'
|
||||
self.assertEqual('http://media.foo.com/',
|
||||
self.settings_module.MEDIA_URL)
|
||||
|
||||
def test_no_end_slash(self):
|
||||
"""
|
||||
MEDIA_URL raises an PendingDeprecationWarning error if it doesn't end in a
|
||||
slash.
|
||||
"""
|
||||
import warnings
|
||||
warnings.filterwarnings('error', 'If set, MEDIA_URL must end with a slash', PendingDeprecationWarning)
|
||||
|
||||
def setattr_settings(settings_module, attr, value):
|
||||
setattr(settings_module, attr, value)
|
||||
|
||||
self.assertRaises(PendingDeprecationWarning, setattr_settings,
|
||||
self.settings_module, 'MEDIA_URL', '/foo')
|
||||
|
||||
self.assertRaises(PendingDeprecationWarning, setattr_settings,
|
||||
self.settings_module, 'MEDIA_URL',
|
||||
'http://media.foo.com')
|
||||
|
||||
def test_double_slash(self):
|
||||
"""
|
||||
If a MEDIA_URL ends in more than one slash, presume they know what
|
||||
they're doing.
|
||||
"""
|
||||
self.settings_module.MEDIA_URL = '/stupid//'
|
||||
self.assertEqual('/stupid//', self.settings_module.MEDIA_URL)
|
||||
|
||||
self.settings_module.MEDIA_URL = 'http://media.foo.com/stupid//'
|
||||
self.assertEqual('http://media.foo.com/stupid//',
|
||||
self.settings_module.MEDIA_URL)
|
||||
|
|
Loading…
Reference in New Issue