Skip to content

API root view return nothing when I enable NamespaceVersioning #2790

@BrickXu

Description

@BrickXu

Hi guys,

I meet a problem when I enable NamespaceVersioning in the settings. but the APIRoot view return a empty dict in the browsable api page.

here is my settings and code segments:

# In the urls.py
urlpatterns = patterns(
    ......
    url(r"^rest_api", include(router.urls, namespace='v1')),
)

# In the routers.py
router = routers.DefaultRouter()
router.register(r'auth/token', auth_views.TokenViewSet, base_name='token')
router.register(r'auth/groups', auth_views.GroupViewSet, base_name='group')
router.register(r'auth/permissions', auth_views.PermissionViewSet, base_name='permission')
router.register(r'labels', common_views.LabelViewSet, base_name='label')
......

# In the settings.py
REST_FRAMEWORK = {
    ......
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning',
    'DEFAULT_VERSION': 'v1',
    'ALLOWED_VERSIONS': ['v1'],
}

Then I debug the code, it shows me a very strange view_name in the rest_framework.reverse.reverse, it seems append the version prefix twice, like "v1:v1:label", it caused NoReverseMatch error.

# In the rest_framework/routers.py
class APIRoot(views.APIView):
    _ignore_model_permissions = True

    def get(self, request, *args, **kwargs):
        ret = OrderedDict()
        namespace = get_resolver_match(request).namespace
        for key, url_name in api_root_dict.items():
            if namespace:
                # here append version prefix for the first time.
                url_name = namespace + ':' + url_name
            try:
                ret[key] = reverse(
                    url_name,
                    request=request,
                    format=kwargs.get('format', None)
                )
            except NoReverseMatch:
                continue

        return Response(ret)

# In the rest_framework/reverse.py
def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra):
    """
    If versioning is being used then we pass any `reverse` calls through
    to the versioning scheme instance, so that the resulting URL
    can be modified if needed.
    """
    scheme = getattr(request, 'versioning_scheme', None)
    if scheme is not None:
        # call NamespaceVersioning.reverse()
        return scheme.reverse(viewname, args, kwargs, request, format, **extra)
    return _reverse(viewname, args, kwargs, request, format, **extra)

# In the rest_framework/versioning.py
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
    if request.version is not None:
        # append version prefix twice!
        viewname = self.get_versioned_viewname(viewname, request)
    return super(NamespaceVersioning, self).reverse(
        viewname, args, kwargs, request, format, **extra
    )

def get_versioned_viewname(self, viewname, request):
    return request.version + ':' + viewname

Do I miss something to set in the settings or I use NamespaceVersioning in the wrong way?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions