使用自定义url_path在@list_route上反转 [英] reverse on @list_route with custom url_path
问题描述
如果我有一个包含以下代码的视图集:
If I have a viewset with the following code:
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'}),
})
I希望这两种方法都能奏效。但是,第二个 reverse
会引发 NoReverseMatch
。检查网址格式(通过导航到一个不存在的网址)将显示以下网址格式:
I would expect both methods to work. However, the second reverse
raises a NoReverseMatch
. Examining the url patterns (by navigating to a non-existing url) shows the following url patterns:
^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
中的错误?
The view name seems to be extraroute-arguments/(?P<thing>[^/]+)
instead of extraroute-arguments
? And indeed, if I use reverse('extraroute-arguments/(?P<thing>[^/]+)', kwargs={'thing': 'something'})
it works. Am I missing something very obvious here, or is this a bug in django-rest-framework
?
这是使用Django 1.8a和django-rest-framework 3.0.5。
This is using Django 1.8a and django-rest-framework 3.0.5.
推荐答案
好,在第二个示例中,您发送 url_path ='arguments /(?P< thing> [^ /] +)'
。 Django REST框架使用它创建 URL模式
和 URL名称
两者。但是实现太纯净了,无法实现
Well, in the second example, you send url_path='arguments/(?P<thing>[^/]+)'
. Django REST framework use it to create both an URL pattern
and a URL Name
. But the implementation is too pure to strip the regex expression.
#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
装饰器,因为它不再需要(这将导致路线冲突)
and then in the views.py remove the @list_route
decorators since its no more needed (and will cause a route clash)
#inside views.py
class ExtraRouteViewset(viewsets.GenericViewSet):
#...
def arguments(self, request, thing):
return Response({
'key': thing,
'reverse': reverse('extraroute-arguments', kwargs={'thing': 'something'}),
})
我不得不提到,这实际上增加了一个硬编码的<$默认 SimpleRouter
中的c $ c> Route 模式(具有用于列表,创建,检索,更新,部分更新,销毁的模式)。这意味着通过此路由器实例注册的每个视图集将能够实现 arguments
方法,并且当正则表达式匹配时将调用此方法
I have to mention that this actually adds a hardcoded Route
pattern inside the default SimpleRouter
(which has patterns for list, create, retrieve, update, partial update, destroy). This means that every viewset which get registered via this router instance will be able to implement an arguments
method and this method will be called when the regex match it.
这篇关于使用自定义url_path在@list_route上反转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!