有条件地限制字段更新

时间:2014-08-20 07:51:31

标签: django django-rest-framework

问题

考虑我有这样的模型和视图集:

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存在类似的问题,但尚未得到回复。

1 个答案:

答案 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模板,我认为更好的方法是在“员工”模板的模板中只读取该字段。用户。

相关问题