我已经为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文档,下面的代码应该可以工作
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文档中,有一个名为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的正确方法是什么?
6条答案
按热度按时间twh00eeo1#
您可以使用
reverse
just add to viewset的basename操作:参见文档的相关部分。
pgvzfuti2#
可以使用
get_urls()
方法在启动时打印给定router
的所有可逆url名称在www.example.com中urls.py将最后一项注册到
router = DefaultRouter()
变量后,可以添加:下次初始化应用程序时,它将打印到stdout,如下所示
其中,“user-list”和“user-detail”是可以指定给
reverse(...)
的名称eeq64g8w3#
基于DRF文件
或者你也可以设置请求。
最后,您可以获得一个反向操作URL并使用它。
von4xj4u4#
如果要专门使用
UserViewset().reverse_action()
,可以通过将basename
和request = None
指定给ViewSet来实现:以及www.example.com网站上urls.py:
然后调用
url = UserViewset().reverse_action('gender')
或url = UserViewset().reverse_action(UserViewSet().gender.url_name)
将返回正确的url。reverse_action()
调用一次时有效,因为ViewSetMixin.as_view()
方法在示例化时覆盖basename
。这可以通过添加GenericViewSet
(或ModelViewSet
,如果首选)的自定义子类来解决,如下所示:并且为特定的视图集子类化这个类,根据需要设置basename。
zc0qhyus5#
答案是
reverse('myuser-gender')
。**注意!**但请记住DRF会将操作名中的
_
替换为-
。这意味着如果操作名是my_pretty_action
,则应反过来使用reverse(app-my-pretty-action)
。anhgbhbe6#
根据您的代码,您希望获得您使用的用户列表
细节
在这里,您可能会注意到,我使用list或detail时将其添加到了相反的位置,因此,如果您添加appname,您可以直接输入它,这是因为我们使用的是viewset