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

Django中如何限制仅任务作者可选NEW/COMPLETED状态,执行者不可选?

实现方案

1. 动态调整序列化器的状态选项

修改serializers.py,在序列化器初始化时根据当前用户身份过滤可选的状态,确保前端只展示用户有权选择的选项:

from rest_framework import serializers
from .models import Tasks
from django.contrib.auth import get_user_model

User = get_user_model()

class TasksSerializer(serializers.ModelSerializer):
    author = serializers.SlugRelatedField(read_only=True, slug_field='username')
    performers = serializers.SlugRelatedField(many=True, read_only=True, slug_field='username')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        user = self.context['request'].user
        instance = kwargs.get('instance')
        
        if instance:
            is_author = instance.author == user
            is_performer = user in instance.performers.all()
            
            # 执行者仅能选择'in progress'和'on finish'
            if not is_author and is_performer:
                allowed_statuses = [('in progress', 'in progress'), ('on finish', 'on finish')]
                self.fields['status'].choices = allowed_statuses

    class Meta:
        model = Tasks
        fields = '__all__'

2. 后端验证状态修改权限

在views.py中重写update方法,增加后端校验,防止用户绕过前端限制直接提交非法状态:

from rest_framework import viewsets, status
from rest_framework.response import Response
from .models import Tasks
from .serializers import TasksSerializer
from rest_framework.permissions import IsAuthenticated

class TasksViewSet(viewsets.ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = Tasks.objects.all().select_related('author').prefetch_related('performers')
    serializer_class = TasksSerializer

    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['status']
    search_fields = ['title', 'text']
    ordering_fields = ['date_create', 'date_update', 'author', 'status']

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        user = request.user

        # 非作者的执行者尝试设置NEW/COMPLETED时直接拒绝
        if instance.author != user and user in instance.performers.all():
            new_status = request.data.get('status')
            if new_status in ['new', 'completed']:
                return Response(
                    {'error': '执行者无法设置NEW或COMPLETED状态'},
                    status=status.HTTP_403_FORBIDDEN
                )

        return super().update(request, *args, **kwargs)

3. 优化权限控制(可选)

如果原IsPerformers权限类无法覆盖作者的访问权限,替换为自定义权限类,确保作者和执行者都能操作对应任务:

from rest_framework.permissions import BasePermission

class IsAuthorOrPerformer(BasePermission):
    def has_object_permission(self, request, view, obj):
        return obj.author == request.user or request.user in obj.performers.all()

然后在视图中更新权限配置:

permission_classes = [IsAuthenticated, IsAuthorOrPerformer]

核心逻辑说明

  • 序列化层修改:控制前端展示的可选状态,提升用户交互体验
  • 视图层校验:从后端拦截非法状态修改,保证数据安全
  • 权限类优化:确保只有任务的作者和执行者具备操作权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:22:42