为什么我不能在Django Rest Framework中的ModelViewSet上使用@action装饰器

时间:2019-04-18 00:28:23

标签: python django django-rest-framework decorator

我在User模型上构建了非常基本的 ViewSet 来欺骗用户。

  • 我想使用ModelViewSet@action装饰器来使代码整洁。
  • 设置IsAuthenticated函数所需的权限(仅以list为例)。这样只有签署的人才能这样做。

这是代码示例。

from rest_framework.decorators import action, list_route
from rest_framework.permissions import IsAuthenticated

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    @action(detail=False, permission_classes=[IsAuthenticated])
    def list(self, request, *args, **kwargs):
        return super(UserViewSet, self).list(request, *args, **kwargs)

但是我遇到了错误

  

不能在以下方法上使用@action装饰器,因为它们是现有路由:list

如果我删除@action,它将很好地工作。我的问题是为什么我不能在现有路由list上使用@action装饰器?

3 个答案:

答案 0 :(得分:2)

@action用于“额外动作”,实际上意味着(如果您检查代码):“未在路由器中明确定义”。因此,如果您使用DefaultRouterSimpleRouter在URL中注册视图,则路由器将抛出此错误。

对于您的情况,您可以修改View.get_permissions,如docs example所示:

from rest_framework.permissions import IsAuthenticated

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get_permissions(self):
        if self.action == 'list':
            return [IsAuthenticated()]
        else:
            return super(self, UserViewSet).get_permissions()

答案 1 :(得分:0)

即使它不能回答该用户的特定问题,我也要张贴任何误导性标题后到达的人,您可以使用@action装饰符作为{{1} }

如下定义视图集:

ModelViewSet

定义路由器和API

from rest_framework import viewsets

class MyModelViewSet(viewsets.ModelViewSet):
    serializer_class = MyModelSerializer
    queryset = MyModel.objects.all()

    @action(detail=True, methods=['get'], url_path='my-action')
    def my_action(self, request, *args, **kwargs):
        """ Get last property-run and return associated results """
        instance = self.get_object()
        # custom code
        custom_response = {"test": "hello world"}
        return Response(custom_response, status=status.HTTP_200_OK)

然后只需通过from rest_framework import routers from django.conf.urls import url router = routers.SimpleRouter() router.register(r'mymodel', MyModelViewSet) urlpatterns += [ url(r'^api/1/', include(router.urls)) ]

对其进行访问

答案 2 :(得分:0)

您尚未导入操作

from rest_framework.decorators import action

请参阅 drf documentation

上的示例