使用自定义 url_path 在 @list_route 上反转
reverse on @list_route with custom url_path
如果我有一个包含以下代码的视图集:
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'}),
})
我希望这两种方法都能奏效。但是,第二个 reverse
引发了 NoReverseMatch
。检查 url 模式(通过导航到不存在的 url)显示以下 url 模式:
^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']
视图名称似乎是 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。
嗯,在第二个例子中,你发送url_path='arguments/(?P<thing>[^/]+)'
。 Django REST 框架 use it to create both an URL pattern
and a URL Name
. But the implementation 过于纯粹,无法去除正则表达式。
使用自定义路由器的解决方案
#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
然后在 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'}),
})
我不得不提一下,这实际上在默认 SimpleRouter
中添加了一个硬编码的 Route
模式(其中包含用于列表、创建、检索、更新、部分更新的模式,销毁)。这意味着通过此路由器实例注册的 每个 视图集将能够实现 arguments
方法,并且当正则表达式匹配时将调用此方法。
如果我有一个包含以下代码的视图集:
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'}),
})
我希望这两种方法都能奏效。但是,第二个 reverse
引发了 NoReverseMatch
。检查 url 模式(通过导航到不存在的 url)显示以下 url 模式:
^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']
视图名称似乎是 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。
嗯,在第二个例子中,你发送url_path='arguments/(?P<thing>[^/]+)'
。 Django REST 框架 use it to create both an URL pattern
and a URL Name
. But the implementation 过于纯粹,无法去除正则表达式。
使用自定义路由器的解决方案
#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
然后在 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'}),
})
我不得不提一下,这实际上在默认 SimpleRouter
中添加了一个硬编码的 Route
模式(其中包含用于列表、创建、检索、更新、部分更新的模式,销毁)。这意味着通过此路由器实例注册的 每个 视图集将能够实现 arguments
方法,并且当正则表达式匹配时将调用此方法。