diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py
index 5911865..4c9c05b 100644
--- a/django/core/handlers/base.py
+++ b/django/core/handlers/base.py
@@ -98,7 +144,11 @@ class BaseHandler(object):
                     urlresolvers.set_urlconf(urlconf)
                     resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
 
-                resolver_match = resolver.resolve(request.path_info)
+            # Use resolved to try to resolve matching URL patterns one by one
+            resolved = {}
+
+            while response is None:
+                resolver_match = resolver.resolve(request.path_info, resolved=resolved)
                 callback, callback_args, callback_kwargs = resolver_match
                 request.resolver_match = resolver_match
 
@@ -108,20 +158,25 @@ class BaseHandler(object):
                     if response:
                         break
 
-            if response is None:
-                wrapped_callback = self.make_view_atomic(callback)
-                try:
-                    response = wrapped_callback(request, *callback_args, **callback_kwargs)
-                except Exception as e:
-                    # If the view raised an exception, run it through exception
-                    # middleware, and if the exception middleware returns a
-                    # response, use that. Otherwise, reraise the exception.
-                    for middleware_method in self._exception_middleware:
-                        response = middleware_method(request, e)
-                        if response:
-                            break
-                    if response is None:
-                        raise
+                if response is None:
+                    wrapped_callback = self.make_view_atomic(callback)
+                    try:
+                        response = wrapped_callback(request, *callback_args, **callback_kwargs)
+                    except urlresolvers.DoesNotResolve:
+                        # Continue resolve URLs if the view raises
+                        # urlresolvers.DoesNotResolve exception to indicate
+                        # the url pattern does not match.
+                        continue
+                    except Exception as e:
+                        # If the view raised an exception, run it through exception
+                        # middleware, and if the exception middleware returns a
+                        # response, use that. Otherwise, reraise the exception.
+                        for middleware_method in self._exception_middleware:
+                            response = middleware_method(request, e)
+                            if response:
+                                break
+                        if response is None:
+                            raise
 
             # Complain if the view returned None (a common error).
             if response is None:
diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index af3df83..055136e 100644
--- a/django/core/urlresolvers.py
+++ b/django/core/urlresolvers.py
@@ -73,6 +73,9 @@ def __repr__(self):
 class Resolver404(Http404):
     pass
 
+class DoesNotResolve(Http404):
+    pass
+
 class NoReverseMatch(Exception):
     # Don't make this raise an error when used in a template.
     silent_variable_failure = True
@@ -205,7 +210,11 @@ class RegexURLPattern(LocaleRegexProvider):
             return
         self._callback_str = prefix + '.' + self._callback_str
 
-    def resolve(self, path):
+    def resolve(self, path, resolved=None, caller=None):
+        if resolved is not None:
+            if caller not in resolved:
+                resolved[caller] = set()
+            resolved[caller].add(self)
         match = self.regex.search(path)
         if match:
             # If there are any named groups, use those as kwargs, ignoring
@@ -310,14 +318,22 @@ class RegexURLResolver(LocaleRegexProvider):
             self._populate()
         return self._app_dict[language_code]
 
-    def resolve(self, path):
+    def resolve(self, path, resolved=None, caller=None):
         tried = []
+        if resolved is None:
+            resolved = {}
+        if caller not in resolved:
+            resolved[caller] = set()
         match = self.regex.search(path)
         if match:
+            if self not in resolved:
+                resolved[self] = set()
             new_path = path[match.end():]
             for pattern in self.url_patterns:
+                if pattern in resolved[self]:
+                    continue
                 try:
-                    sub_match = pattern.resolve(new_path)
+                    sub_match = pattern.resolve(new_path, resolved=resolved, caller=self)
                 except Resolver404 as e:
                     sub_tried = e.args[0].get('tried')
                     if sub_tried is not None:
@@ -330,7 +344,11 @@ class RegexURLResolver(LocaleRegexProvider):
                         sub_match_dict.update(sub_match.kwargs)
                         return ResolverMatch(sub_match.func, sub_match.args, sub_match_dict, sub_match.url_name, self.app_name or sub_match.app_name, [self.namespace] + sub_match.namespaces)
                     tried.append([pattern])
+                resolved[self].add(pattern)
+            del resolved[self]
+            resolved[caller].add(self)
             raise Resolver404({'tried': tried, 'path': new_path})
+        resolved[caller].add(self)
         raise Resolver404({'path' : path})
 
     @property
--- a/tests/view_tests/tests/test_specials.py
+++ b/tests/view_tests/tests/test_specials.py
@@ -37,3 +37,32 @@ class URLHandling(TestCase):
         response = self.client.get('/permanent_nonascii_redirect/')
         self.assertRedirects(response, self.redirect_target, status_code=301)
 
+    def test_overlapping_urls_reverse(self):
+        from django.core import urlresolvers
+        url = urlresolvers.reverse('overlapping_view1', kwargs={'title': 'sometitle'})
+        self.assertEqual(url, '/overlapping_view/sometitle/')
+        url = urlresolvers.reverse('overlapping_view2', kwargs={'author': 'someauthor'})
+        self.assertEqual(url, '/overlapping_view/someauthor/')
+
+    def test_overlapping_urls_resolve(self):
+        response = self.client.get('/overlapping_view/sometitle/')
+        self.assertContains(response, 'overlapping_view2')
+
+    def test_overlapping_urls_not_resolve(self):
+        response = self.client.get('/no_overlapping_view/sometitle/')
+        self.assertEqual(response.status_code, 404)
+
+    def test_nested_overlapping_urls_reverse(self):
+        from django.core import urlresolvers
+        url = urlresolvers.reverse('nested_overlapping_view1', kwargs={'title': 'sometitle'})
+        self.assertEqual(url, '/nested/overlapping_view/sometitle/')
+        url = urlresolvers.reverse('nested_overlapping_view2', kwargs={'author': 'someauthor'})
+        self.assertEqual(url, '/nested/overlapping_view/someauthor/')
+
+    def test_nested_overlapping_urls_resolve(self):
+        response = self.client.get('/nested/overlapping_view/sometitle/')
+        self.assertContains(response, 'overlapping_view2')
+
+    def test_nested_overlapping_urls_not_resolve(self):
+        response = self.client.get('/nested/no_overlapping_view/sometitle/')
+        self.assertEqual(response.status_code, 404)
--- a/tests/view_tests/generic_urls.py
+++ b/tests/view_tests/generic_urls.py
@@ -1,7 +1,7 @@
 # -*- coding:utf-8 -*-
 from __future__ import absolute_import, unicode_literals
 
-from django.conf.urls import patterns, url
+from django.conf.urls import patterns, url, include
 from django.views.generic import RedirectView
 
 from . import views
@@ -54,4 +54,14 @@ urlpatterns += patterns('view_tests.views',
     (r'^shortcuts/render/status/$', 'render_view_with_status'),
     (r'^shortcuts/render/current_app/$', 'render_view_with_current_app'),
     (r'^shortcuts/render/current_app_conflict/$', 'render_view_with_current_app_conflict'),
+    (r'^nested/', include(patterns('view_tests.views',
+        url(r'^overlapping_view/(?P<title>[a-z]+)/$', 'overlapping_view1', name='nested_overlapping_view1'),
+        url(r'^overlapping_view/(?P<author>[a-z]+)/$', 'overlapping_view2', name='nested_overlapping_view2'),
+        url(r'^overlapping_view/(?P<keywords>[a-z]+)/$', 'overlapping_view3', name='nested_overlapping_view3'),
+        url(r'^no_overlapping_view/(?P<keywords>[a-z]+)/$', 'no_overlapping_view', name='nested_no_overlapping_view'),
+    ))),
+    url(r'^overlapping_view/(?P<title>[a-z]+)/$', 'overlapping_view1', name='overlapping_view1'),
+    url(r'^overlapping_view/(?P<author>[a-z]+)/$', 'overlapping_view2', name='overlapping_view2'),
+    url(r'^overlapping_view/(?P<keywords>[a-z]+)/$', 'overlapping_view3', name='overlapping_view3'),
+    url(r'^no_overlapping_view/(?P<keywords>[a-z]+)/$', 'no_overlapping_view', name='no_overlapping_view'),
 )
--- a/tests/view_tests/views.py
+++ b/tests/view_tests/views.py
@@ -3,7 +3,7 @@ from __future__ import absolute_import
 import sys
 
 from django.core.exceptions import PermissionDenied, SuspiciousOperation
-from django.core.urlresolvers import get_resolver
+from django.core.urlresolvers import get_resolver, DoesNotResolve
 from django.http import HttpResponse, HttpResponseRedirect
 from django.shortcuts import render_to_response, render
 from django.template import Context, RequestContext, TemplateDoesNotExist
@@ -273,6 +273,17 @@ class Klass(object):
 def sensitive_method_view(request):
     return Klass().method(request)
 
+def overlapping_view1(request, title=None):
+    raise DoesNotResolve
+
+def overlapping_view2(request, author=None):
+    return HttpResponse("overlapping_view2")
+
+def overlapping_view3(request, keywords=None):
+    return HttpResponse("overlapping_view3")
+
+def no_overlapping_view(request, keywords=None):
+    raise DoesNotResolve
 
 @sensitive_variables('sauce')
 @sensitive_post_parameters('bacon-key', 'sausage-key')
