diff --git a/django/conf/__init__.py b/django/conf/__init__.py
index bda0ef3..7daf227 100644
--- a/django/conf/__init__.py
+++ b/django/conf/__init__.py
@@ -11,6 +11,7 @@ import re
 import time     # Needed for Windows
 
 from django.conf import global_settings
+from django.core.exceptions import ImproperlyConfigured
 from django.utils.functional import LazyObject
 from django.utils import importlib
 
@@ -59,7 +60,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 == "MEDIA_URL" and value and value[-1] != '/':
+            raise ImproperlyConfigured('If set, MEDIA_URL must end in a '
+                                       'slash.')
+        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):
@@ -114,7 +127,8 @@ class Settings(object):
             os.environ['TZ'] = self.TIME_ZONE
             time.tzset()
 
-class UserSettingsHolder(object):
+
+class UserSettingsHolder(BaseSettings):
     """
     Holder for user configured settings.
     """
@@ -138,5 +152,5 @@ class UserSettingsHolder(object):
     # For Python < 2.6:
     __members__ = property(lambda self: self.__dir__())
 
-settings = LazySettings()
 
+settings = LazySettings()
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index 6033297..4a9b9e2 100644
--- a/django/conf/global_settings.py
+++ b/django/conf/global_settings.py
@@ -263,7 +263,7 @@ DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
 MEDIA_ROOT = ''
 
 # URL that handles the media served from MEDIA_ROOT.
-# Example: "http://media.lawrence.com"
+# Example: "http://media.lawrence.com/"
 MEDIA_URL = ''
 
 # List of upload handler classes to be applied in order.
diff --git a/django/conf/project_template/settings.py b/django/conf/project_template/settings.py
index c49df24..4edd67f 100644
--- a/django/conf/project_template/settings.py
+++ b/django/conf/project_template/settings.py
@@ -48,8 +48,8 @@ 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).
-# Examples: "http://media.lawrence.com", "http://example.com/media/"
+# trailing slash.
+# Examples: "http://media.lawrence.com/", "http://example.com/media/"
 MEDIA_URL = ''
 
 # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
index b5556de..58738a5 100644
--- a/docs/ref/settings.txt
+++ b/docs/ref/settings.txt
@@ -1072,12 +1072,9 @@ MEDIA_URL
 Default: ``''`` (Empty string)
 
 URL that handles the media served from ``MEDIA_ROOT``.
-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"``
+It must end in a slash if set to a non-empty value.
 
 .. setting:: MIDDLEWARE_CLASSES
 
diff --git a/docs/releases/1.3.txt b/docs/releases/1.3.txt
index 51de6fd..52f1758 100644
--- a/docs/releases/1.3.txt
+++ b/docs/releases/1.3.txt
@@ -81,6 +81,22 @@ If you are currently using the ``mod_python`` request handler, it is strongly
 encouraged you redeploy your Django instances using :doc:`mod_wsgi
 </howto/deployment/modwsgi>`.
 
+Other changes in Django 1.3
+===========================
+
+``MEDIA_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`` as long as it is not
+blank. This ensures there is a consistent way to combine ``MEDIA_URL`` in
+templates.
+
+Project settings modules which provide a ``MEDIA_URL`` without a trailing slash
+will now raise an ``ImproperlyConfigured`` error.
+
 What's new in Django 1.3
 ========================
 
diff --git a/tests/regressiontests/settings_tests/tests.py b/tests/regressiontests/settings_tests/tests.py
index fa217b1..08d5b0a 100644
--- a/tests/regressiontests/settings_tests/tests.py
+++ b/tests/regressiontests/settings_tests/tests.py
@@ -1,5 +1,11 @@
 import unittest
-from django.conf import settings
+from django.conf import settings, UserSettingsHolder, global_settings
+from django.core.exceptions import ImproperlyConfigured
+
+    
+def setattr_settings(settings_module, attr, value):
+    setattr(settings_module, attr, value)
+
 
 class SettingsTests(unittest.TestCase):
 
@@ -15,3 +21,60 @@ class SettingsTests(unittest.TestCase):
 
     def test_settings_delete_wrapped(self):
         self.assertRaises(TypeError, delattr, settings, '_wrapped')
+
+
+class MediaURLTests(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 ImproperlyConfigured 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 ImproperlyConfigured error if it doesn't end in a
+        slash.
+        """
+        self.assertRaises(ImproperlyConfigured, setattr_settings,
+                          self.settings_module, 'MEDIA_URL', '/foo')
+
+        self.assertRaises(ImproperlyConfigured, 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)
+
+
+class MediaURLUserSettingsHolderTests(unittest.TestCase):
+    settings_module = UserSettingsHolder(global_settings)
