You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST自定义权限报错:Update Task APIView对象无action属性

问题根因

  1. 报错'Update Task APIView' object has no attribute 'action'的原因:action是DRF ViewSet类的专属属性,你使用的UpdateAPIView、DestroyAPIView属于通用类视图,没有该属性,导致自定义权限类运行时抛出异常,权限校验逻辑直接失效,所以没有正常拦截非所有者的修改、删除操作。
  2. 权限配置冗余:更新、删除视图的权限类同时配置了IsAuthenticatedOrReadOnly,该权限会允许所有登录用户执行写操作,和自定义的所有者校验逻辑冲突。

修改步骤

1. 修复自定义权限类Permissions.py

把原来基于view.action的判断逻辑改为基于请求方法判断,适配通用类视图场景:

from rest_framework import permissions


class IsOwner(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):
        # GET、HEAD、OPTIONS这类只读请求直接放行,对应你原有的查询放行需求
        if request.method in permissions.SAFE_METHODS:
            return True
        # 增删改操作需要任务所有者才能执行
        return obj.user == request.user

2. 修正视图层权限配置和创建逻辑

修改Views.py中的视图配置,移除冗余权限、补充创建任务时的用户绑定逻辑:

class TaskViewSet(ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
    permission_classes = [permissions.IsAuthenticated, IsOwner,]

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


class ListTaskAPIView(generics.ListAPIView):
    serializer_class = TaskSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    model= Task
    def get_queryset(self):
        """
        Optionally restricts the returned purchases to a given user,
        by filtering against a `username` query parameter in the URL.
        """
        query = self.request.GET.get('search')
        if query:
            object_list = self.model.objects.filter(Q(title__icontains=query) | Q(text__icontains=query))
        else:
            object_list = self.model.objects.all()
        return object_list


class CreateTaskAPIView(ListCreateAPIView):
    """This endpoint allows for creation of a todo"""
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
    # 要求登录才能创建任务
    permission_classes = [permissions.IsAuthenticated]
    # 新增:创建时自动绑定当前登录用户为任务所有者
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


class UpdateTaskAPIView(UpdateAPIView):
    """This endpoint allows for updating a specific todo by passing in the id of the todo to update"""
    serializer_class = TaskSerializer
    # 移除冗余的IsAuthenticatedOrReadOnly,保留登录+所有者校验
    permission_classes = [permissions.IsAuthenticated, IsOwner,]
    queryset = Task.objects.all()

class DeleteTaskAPIView(DestroyAPIView):
    """This endpoint allows for deletion of a specific Todo from the database"""
    serializer_class = TaskSerializer
    # 移除冗余的IsAuthenticatedOrReadOnly,保留登录+所有者校验
    permission_classes = [permissions.IsAuthenticated, IsOwner]
    queryset = Task.objects.all()

可选优化

你当前同时定义了TaskViewSet和多个单独的通用视图,urls.py中实际使用的是单独视图的路由,TaskViewSet没有配置路由未生效。如果不需要多套接口,可以直接使用ViewSet+Router的方式简化代码,不需要单独写增删改查的视图类。

内容的提问来源于stack exchange,提问作者Montio5

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 10:45:04