使用自定义url_path反转@list_route

Mic*_*hel 10 python django django-rest-framework

如果我有一个包含以下代码的视图集:

class ExtraRouteViewset(viewsets.GenericViewSet):
    @list_route(methods=['get'])
    def somefunction(self, request):
        return Response({
            'key': 'value',
            'reverse': reverse('extraroute-somefunction'),
        })

    @list_route(methods=['get'], url_path='arguments/(?P<thing>[^/]+)')
    def arguments(self, request, thing):
        return Response({
            'key': thing,
            'reverse': reverse('extraroute-arguments', kwargs={'thing': 'something'}),
        })
Run Code Online (Sandbox Code Playgroud)

我希望这两种方法都有效.然而,第二个reverse提出了一个NoReverseMatch.检查网址格式(通过导航到不存在的网址)显示以下网址格式:

^demo/ ^ ^extraroute/arguments/(?P<thing>[^/]+)/$ [name='extraroute-arguments/(?P<thing>[^/]+)']
^demo/ ^ ^extraroute/arguments/(?P<thing>[^/]+)/\.(?P<format>[a-z0-9]+)$ [name='extraroute-arguments/(?P<thing>[^/]+)']
^demo/ ^ ^extraroute/somefunction/$ [name='extraroute-somefunction']
^demo/ ^ ^extraroute/somefunction/\.(?P<format>[a-z0-9]+)$ [name='extraroute-somefunction']
Run Code Online (Sandbox Code Playgroud)

视图名称似乎extraroute-arguments/(?P<thing>[^/]+)代替extraroute-arguments?事实上,如果我使用reverse('extraroute-arguments/(?P<thing>[^/]+)', kwargs={'thing': 'something'})它的话.我错过了一些非常明显的东西,或者这是一个错误django-rest-framework吗?

这是使用Django 1.8a和django-rest-framework 3.0.5.

Tod*_*dor 8

那么,在第二个例子中,你发送url_path='arguments/(?P<thing>[^/]+)'.Django REST框架使用它来创建一个URL pattern和一个URL Name.但实现过于纯粹,无法剥离正则表达式.

解决方案与自定义路由器

#inside urls.py
router = SimpleRouter()
router.routes.append(
    Route(
        url=r'^{prefix}/arguments/(?P<thing>[^/]+)$',
        name='{basename}-arguments',
        mapping={
            'get': 'arguments',
        },
        initkwargs={}
    ),
)
router.register('extraroute', ExtraRouteViewset, base_name='extraroute')
urlpatterns = router.urls
Run Code Online (Sandbox Code Playgroud)

然后在views.py中删除@list_route装饰器,因为它不再需要(并且会导致路由冲突)

#inside views.py
class ExtraRouteViewset(viewsets.GenericViewSet):
    #...

    def arguments(self, request, thing):
        return Response({
            'key': thing,
            'reverse': reverse('extraroute-arguments', kwargs={'thing': 'something'}),
        })
Run Code Online (Sandbox Code Playgroud)

我必须提到,这实际上Route在默认内部添加了一个硬编码模式SimpleRouter (其中包含列表,创建,检索,更新,部分更新,销毁的模式).这意味着通过此路由器实例注册的每个视图集都能够实现一个arguments方法,并且当正则表达式匹配时,将调用此方法.