Handling the fallback in reverse

This commit is contained in:
Ion Scerbatiuc 2015-03-19 16:12:28 -07:00
parent 90280a3437
commit fac2785341
3 changed files with 36 additions and 12 deletions

View File

@ -3,6 +3,7 @@ Provide urlresolver functions that return fully qualified URLs or view names
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
from django.core.urlresolvers import reverse as django_reverse from django.core.urlresolvers import reverse as django_reverse
from django.core.urlresolvers import NoReverseMatch
from django.utils import six from django.utils import six
from django.utils.functional import lazy from django.utils.functional import lazy
@ -15,7 +16,13 @@ def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra
""" """
scheme = getattr(request, 'versioning_scheme', None) scheme = getattr(request, 'versioning_scheme', None)
if scheme is not None: if scheme is not None:
return scheme.reverse(viewname, args, kwargs, request, format, **extra) try:
return scheme.reverse(viewname, args, kwargs, request, format, **extra)
except NoReverseMatch:
# In case the versioning scheme reversal fails, fallback to the
# default implementation
pass
return _reverse(viewname, args, kwargs, request, format, **extra) return _reverse(viewname, args, kwargs, request, format, **extra)

View File

@ -1,7 +1,6 @@
# coding: utf-8 # coding: utf-8
from __future__ import unicode_literals from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import NoReverseMatch
from rest_framework import exceptions from rest_framework import exceptions
from rest_framework.compat import unicode_http_header from rest_framework.compat import unicode_http_header
from rest_framework.reverse import _reverse from rest_framework.reverse import _reverse
@ -123,16 +122,7 @@ class NamespaceVersioning(BaseVersioning):
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra): def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
if request.version is not None: if request.version is not None:
versioned_viewname = self.get_versioned_viewname(viewname, request) viewname = self.get_versioned_viewname(viewname, request)
try:
return super(NamespaceVersioning, self).reverse(
versioned_viewname, args, kwargs, request, format, **extra
)
except NoReverseMatch:
# If the versioned viewname lookup fails, fallback to the
# default reversal, since it may be a non-API view
pass
return super(NamespaceVersioning, self).reverse( return super(NamespaceVersioning, self).reverse(
viewname, args, kwargs, request, format, **extra viewname, args, kwargs, request, format, **extra
) )

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from django.core.urlresolvers import NoReverseMatch
from django.test import TestCase from django.test import TestCase
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
from rest_framework.test import APIRequestFactory from rest_framework.test import APIRequestFactory
@ -16,6 +17,18 @@ urlpatterns = patterns(
) )
class MockVersioningScheme(object):
def __init__(self, raise_error=False):
self.raise_error = raise_error
def reverse(self, *args, **kwargs):
if self.raise_error:
raise NoReverseMatch()
return 'http://scheme-reversed/view'
class ReverseTests(TestCase): class ReverseTests(TestCase):
""" """
Tests for fully qualified URLs when using `reverse`. Tests for fully qualified URLs when using `reverse`.
@ -26,3 +39,17 @@ class ReverseTests(TestCase):
request = factory.get('/view') request = factory.get('/view')
url = reverse('view', request=request) url = reverse('view', request=request)
self.assertEqual(url, 'http://testserver/view') self.assertEqual(url, 'http://testserver/view')
def test_reverse_with_versioning_scheme(self):
request = factory.get('/view')
request.versioning_scheme = MockVersioningScheme()
url = reverse('view', request=request)
self.assertEqual(url, 'http://scheme-reversed/view')
def test_reverse_with_versioning_scheme_fallback_to_default_on_error(self):
request = factory.get('/view')
request.versioning_scheme = MockVersioningScheme(raise_error=True)
url = reverse('view', request=request)
self.assertEqual(url, 'http://testserver/view')