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

如何禁止普通用户修改工单status,仅允许管理员与超级用户操作?

解决方案

1. 修复序列化器的status字段定义

你当前的status字段写法错误,需替换为符合ForeignKey关联的正确字段类型:

class TicketSerializerUpdate(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = Ticket
        fields = "__all__"

如果需要前端显示状态文本而非ID,可改用SlugRelatedField:

status = serializers.SlugRelatedField(
    queryset=Status.objects.all(),
    slug_field='status'
)

2. 序列化器层面动态控制字段权限

重写序列化器的get_fields方法,根据当前用户权限决定status字段的展示/编辑权限:

class TicketSerializerUpdate(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = Ticket
        fields = "__all__"

    def get_fields(self):
        fields = super().get_fields()
        request = self.context.get('request')
        if request and not (request.user.is_staff or request.user.is_superuser):
            # 方案1:移除字段,前端完全看不到status按钮
            fields.pop('status')
            # 方案2:设置为只读,前端按钮置灰不可编辑
            # fields['status'].read_only = True
        return fields

需要在视图中把请求对象传入序列化器上下文:

def get_serializer_context(self):
    context = super().get_serializer_context()
    context['request'] = self.request
    return context

3. 视图层面添加权限校验(双重保障)

自定义权限类,防止恶意请求绕过前端直接修改status:

from rest_framework import permissions

class CanModifyTicketStatus(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        # 只读请求(如GET)允许所有用户查看
        if request.method in permissions.SAFE_METHODS:
            return True
        # 管理员/超级用户允许修改所有工单的状态
        if request.user.is_staff or request.user.is_superuser:
            return True
        # 普通用户仅能修改自己的工单,且不能提交status字段
        if obj.user == request.user:
            return 'status' not in request.data
        return False

在Update视图中配置该权限:

from rest_framework.generics import UpdateAPIView

class TicketUpdateView(UpdateAPIView):
    queryset = Ticket.objects.all()
    serializer_class = TicketSerializerUpdate
    permission_classes = [CanModifyTicketStatus]

推荐方案

结合序列化器字段控制和视图权限校验:

  • 序列化器对普通用户隐藏/只读status字段,保证前端交互符合需求
  • 权限类拦截非法的后端请求,避免数据被恶意篡改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:50:44