Skip to content

Commit fac2785

Browse files
committed
Handling the fallback in reverse
1 parent 90280a3 commit fac2785

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

rest_framework/reverse.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44
from __future__ import unicode_literals
55
from django.core.urlresolvers import reverse as django_reverse
6+
from django.core.urlresolvers import NoReverseMatch
67
from django.utils import six
78
from django.utils.functional import lazy
89

@@ -15,7 +16,13 @@ def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra
1516
"""
1617
scheme = getattr(request, 'versioning_scheme', None)
1718
if scheme is not None:
18-
return scheme.reverse(viewname, args, kwargs, request, format, **extra)
19+
try:
20+
return scheme.reverse(viewname, args, kwargs, request, format, **extra)
21+
except NoReverseMatch:
22+
# In case the versioning scheme reversal fails, fallback to the
23+
# default implementation
24+
pass
25+
1926
return _reverse(viewname, args, kwargs, request, format, **extra)
2027

2128

rest_framework/versioning.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# coding: utf-8
22
from __future__ import unicode_literals
33
from django.utils.translation import ugettext_lazy as _
4-
from django.core.urlresolvers import NoReverseMatch
54
from rest_framework import exceptions
65
from rest_framework.compat import unicode_http_header
76
from rest_framework.reverse import _reverse
@@ -123,16 +122,7 @@ def determine_version(self, request, *args, **kwargs):
123122

124123
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
125124
if request.version is not None:
126-
versioned_viewname = self.get_versioned_viewname(viewname, request)
127-
try:
128-
return super(NamespaceVersioning, self).reverse(
129-
versioned_viewname, args, kwargs, request, format, **extra
130-
)
131-
except NoReverseMatch:
132-
# If the versioned viewname lookup fails, fallback to the
133-
# default reversal, since it may be a non-API view
134-
pass
135-
125+
viewname = self.get_versioned_viewname(viewname, request)
136126
return super(NamespaceVersioning, self).reverse(
137127
viewname, args, kwargs, request, format, **extra
138128
)

tests/test_reverse.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import unicode_literals
22
from django.conf.urls import patterns, url
3+
from django.core.urlresolvers import NoReverseMatch
34
from django.test import TestCase
45
from rest_framework.reverse import reverse
56
from rest_framework.test import APIRequestFactory
@@ -16,6 +17,18 @@ def null_view(request):
1617
)
1718

1819

20+
class MockVersioningScheme(object):
21+
22+
def __init__(self, raise_error=False):
23+
self.raise_error = raise_error
24+
25+
def reverse(self, *args, **kwargs):
26+
if self.raise_error:
27+
raise NoReverseMatch()
28+
29+
return 'http://scheme-reversed/view'
30+
31+
1932
class ReverseTests(TestCase):
2033
"""
2134
Tests for fully qualified URLs when using `reverse`.
@@ -26,3 +39,17 @@ def test_reversed_urls_are_fully_qualified(self):
2639
request = factory.get('/view')
2740
url = reverse('view', request=request)
2841
self.assertEqual(url, 'http://testserver/view')
42+
43+
def test_reverse_with_versioning_scheme(self):
44+
request = factory.get('/view')
45+
request.versioning_scheme = MockVersioningScheme()
46+
47+
url = reverse('view', request=request)
48+
self.assertEqual(url, 'http://scheme-reversed/view')
49+
50+
def test_reverse_with_versioning_scheme_fallback_to_default_on_error(self):
51+
request = factory.get('/view')
52+
request.versioning_scheme = MockVersioningScheme(raise_error=True)
53+
54+
url = reverse('view', request=request)
55+
self.assertEqual(url, 'http://testserver/view')

0 commit comments

Comments
 (0)