如何禁止普通用户修改工单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
相关产品推荐
相关产品推荐

