Django 有条件地限制字段更新 问题

Django 有条件地限制字段更新 问题,django,django-rest-framework,Django,Django Rest Framework,假设我有这样一个模型和一个视图集: class Employee(models.Model): name = models.CharField(max_length=100) salary = models.PositiveIntegerField() class EmployeeViewSet(viewsets.ModelViewSet): model = Employee 我希望能够根据用户发出的请求限制字段更新 例如,员工可以更改姓名,但不能更改工资;另一方面,

假设我有这样一个模型和一个视图集:

class Employee(models.Model):
    name = models.CharField(max_length=100)
    salary = models.PositiveIntegerField()

class EmployeeViewSet(viewsets.ModelViewSet):
    model = Employee
我希望能够根据用户发出的请求限制字段更新

例如,员工可以更改姓名,但不能更改工资;另一方面,经理可以同时更改员工的工资和姓名

我还需要提供适当的HTTP状态代码,指示特定字段的更改是禁止的,例如,如果一名员工将一个有效负载的薪资字段更改为403而不是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有效负载中的salary字段来防止更改salary。如果名称有效,则返回200 OK(而不是403 FORBIDDEN),这使得用户相信他也设法更改了工资,但事实并非如此


我发现一个邮件列表也有类似的问题,尽管它还没有得到回复。

我认为您不需要两个序列化程序

我会这样做: -创建自定义权限类- -更新时使用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禁止

当然,如果您使用的是django模板,在我看来,更好的方法是在“employee”用户的模板中将该字段设置为只读