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

nos*_*nos 13 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):
        ....
Run Code Online (Sandbox Code Playgroud)

并且以常规方式将视图集注册到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)),                                               
]   
Run Code Online (Sandbox Code Playgroud)

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

根据django文档,以下代码应该工作

reverse('admin:app_list', kwargs={'app_label': 'auth'})
# '/admin/auth/'
Run Code Online (Sandbox Code Playgroud)

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

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

django-restframework文档中,有一个名为的函数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
Run Code Online (Sandbox Code Playgroud)

撤消该操作的URL的正确方法是什么?

小智 29

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

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

#router = routers.DefaultRouter()
#router.register(r'users', UserViewSet)
#...
import pprint
pprint.pprint(router.get_urls())
Run Code Online (Sandbox Code Playgroud)

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

[<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]+)/?$>,         
#...
]
Run Code Online (Sandbox Code Playgroud)

其中“user-list”和“user-detail”是可以指定的名称reverse(...)


nev*_*ner 10

您可以使用reverseadd添加到viewset的basename操作:

reverse('myuser-gender') 
Run Code Online (Sandbox Code Playgroud)

请参阅文档的相关部分

  • 您可能需要添加应用程序名称:`reverse('api:myuser-gender')` (4认同)
  • 就像 @MatthewHegarty 指出的那样,您可能还需要添加应用程序命名空间。如果您正在调试,您可以通过先运行“python manage.py show_urls”来节省时间,然后从那里找到 URL 名称。 (3认同)
  • @AJ [文档](https://www.django-rest-framework.org/api-guide/viewsets/#reversing-action-urls)中的示例:`view.reverse_action('set-password', args=[ ‘1’])` (2认同)