考虑我有这样的模型和视图集:
class Employee(models.Model):
name = models.CharField(max_length=100)
salary = models.PositiveIntegerField()
class EmployeeViewSet(viewsets.ModelViewSet):
model = Employee
我希望能够根据用户发出请求限制字段更新。
例如,员工应该能够改变他的名字,而不是工资;另一方面,经理可以改变员工的工资和姓名。
我还需要提供正确的HTTP状态代码,指示禁止特定的字段更改,例如,如果员工PUT的薪资字段已更改,则应该获得403 FORBIDDEN而不是200 OK。
我尝试根据请求的用户更改序列化程序,并制作了几个不同的序列化程序,每个序列化程序都指定了不同的只读字段:
class EmployeeRestrictedSerializer(serializers.HyperlinkedModelSerializer):
class Meta(object):
model = Employee
fields = ('name', 'salary')
read_only_fields = ('salary',)
class EmployeeViewSet(viewsets.ModelViewSet):
model = Employee
def get_serializer_class(self):
if not self.request.user.is_staff:
return EmployeeRestrictedSerializer
return super(EmployeeViewSet, self).get_serializer_class()
这种方法可以完全忽略PUT有效载荷中的工资字段,从而防止工资被改变。另外,如果名称有效,则返回200 OK(而不是403 FORBIDDEN),使用户相信他也设法改变了工资,但事实并非如此。
我发现邮件列表post存在类似的问题,但尚未得到回复。
答案 0 :(得分:1)
我认为你不需要两个序列化器。
在这里我将如何做到这一点: - 创建自定义权限类 - see here - 使用PATCH而不是PUT进行更新,因为PATCH允许某些字段从请求中丢失 - 在 has_object_permission 方法中,检查您的用户类型并返回适当的响应:
def has_object_permission(self, request, view, obj):
if request.user is manager:
return True
# Employee must not try to modify 'salary' field.
salary = request.DATA.get('salary', None)
return salary is None
当员工试图更改工资字段时,默认情况下会返回403 Forbidden。
当然,如果您使用的是django模板,我认为更好的方法是在“员工”模板的模板中只读取该字段。用户。