如何在Django restframework中反转ViewSet自定义操作的URL

时间:2018-07-13 04:11:30

标签: python django url django-rest-framework

我已经为ViewSet定义了自定义操作

from rest_framework import viewsets

class UserViewSet(viewsets.ModelViewSet):
    @action(methods=['get'], detail=False, permission_classes=[permissions.AllowAny]) 
    def gender(self, request):
        ....

然后将视图集以常规方式注册到url

from django.conf.urls import url, include                                          

from rest_framework import routers                                                 
from api import views                                                              


router = routers.DefaultRouter()                                                   
router.register(r'users', views.UserViewSet, base_name='myuser')                   

urlpatterns = [                                                                    
    url(r'^', include(router.urls)),                                               
]   

URL /api/users/gender/有效。但是我不知道如何在单元测试中使用reverse来获得它。 (我当然可以对这个URL进行硬编码,但是从代码中获取它会很好)

根据django documentation,以下代码应正常工作

reverse('admin:app_list', kwargs={'app_label': 'auth'})
# '/admin/auth/'

但是我尝试了以下方法,但它们不起作用

reverse('myuser-list', kwargs={'app_label':'gender'})
# errors out
reverse('myuser-list', args=('gender',))
# '/api/users.gender'

django-restframework documentation中,有一个名为reverse_action的函数。但是,我的尝试没有效果

from api.views import UserViewSet
a = UserViewSet()
a.reverse_action('gender') # error out
from django.http import HttpRequest
req = HttpRequest()
req.method = 'GET'
a.reverse_action('gender', request=req)  # still error out

反向执行该操作的URL的正确方法是什么?

3 个答案:

答案 0 :(得分:4)

您可以使用reverse仅添加到视图集的基本名称操作中:

reverse('myuser-gender') 

请参阅文档的related part

答案 1 :(得分:3)

您可以在启动时使用 router 方法打印给定 get_urls() 的所有可逆 url 名称

在将最后一项注册到 router = DefaultRouter() 变量后的 urls.py 中,您可以添加:

#router = routers.DefaultRouter()
#router.register(r'users', UserViewSet)
#...
import pprint
pprint.pprint(router.get_urls())

下次初始化您的应用程序时,它将打印到标准输出

[<RegexURLPattern user-list ^users/$>,
 <RegexURLPattern user-list ^users\.(?P<format>[a-z0-9]+)/?$>,
 <RegexURLPattern user-detail ^users/(?P<pk>[^/.]+)/$>,
 <RegexURLPattern user-detail ^users/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>,         
#...
]

其中 'user-list' 和 'user-detail' 是可以赋予​​ reverse(...) 的名称

答案 2 :(得分:0)

基于DRF Doc

from rest_framework import routers

router = routers.DefaultRouter()

view = UserViewSet()
view.basename = router.get_default_basename(UserViewSet)
view.request = None

或者您可以根据需要设置请求。

view.request = req

最后,您可以获取并使用反向操作网址。

url = view.reverse_action('gender', args=[])