Django Rest Framework - 可以允许unadmin用户只更改序列化程序的一个字段,管理员用户更改所有字段?

时间:2015-10-29 20:41:56

标签: django django-rest-framework

这是我的序列化器:

class LocationSerializer(serializers.ModelSerializer):

    class Meta:
        model = Location
        fields = ('city', 'users', 'locationName', 'locationCode')

    def create(self, validated_data):

        location = Location.objects.create(
                city = validated_data['city'],
                locationName = validated_data['locationName'],
                locationCode = validated_data['locationCode'],
        )

        return location

    def update(self, instance, validated_data):
        raise_errors_on_nested_writes('update', self, validated_data)
        # Only admin users are allowed to change the location name and code.
        instance.locationName = validated_data.get('locationName', instance.locationName)
        instance.locationCode = validated_data.get('locationCode', instance.locationCode)

        # All users are allowed to add themselves to the 'users' list.
        if validated_data.get('user', None):
            instance.users.add(self.request.user)

        return instance

对我来说,实现这一目标的最佳途径是什么? (我已经评论了上面的代码,提到了我想要实现的目标 - 我希望只有管理员用户能够更改位置名称和代码,但我希望任何经过身份验证的用户都能够将自己添加到“用户”列表中)。

1 个答案:

答案 0 :(得分:2)

也许您可以考虑使用两个不同序列化程序的逻辑,具体取决于当前用户。您可以根据当前用户和请求类型(调度方法名称)在get_serilizer_class中做出决定。因此,您可以将视图逻辑与串行器逻辑分开。

使用序列化程序,您可以使用一些视图上下文数据来检查当前用户:

class LocationSerializer(serializers.ModelSerializer):

    class Meta:
        model = Location
        fields = ('city', 'users', 'locationName', 'locationCode')

    def create(self, validated_data):

        location = Location.objects.create(
                city = validated_data['city'],
                locationName = validated_data['locationName'],
                locationCode = validated_data['locationCode'],
        )

        return location

    def update(self, instance, validated_data):
        raise_errors_on_nested_writes('update', self, validated_data)
        # Only admin users are allowed to change the location name and code.
        if self.context['request'].user.is_staff:
            instance.locationName = validated_data.get('locationName', instance.locationName)
            instance.locationCode = validated_data.get('locationCode', instance.locationCode)

        # All users are allowed to add themselves to the 'users' list.
        if validated_data.get('user', None):
            instance.users.add(self.request.user)

        return instance

简化设计,如首先建议的那样:

class AdminLocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Location
        fields = ('city', 'users', 'locationName', 'locationCode')


class UserLocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Location
        fields = ('city', 'users', 'locationName', 'locationCode')
        read_only_fields = ('locationName', 'locationCode')

class LocationViewSet(generics.ModelViewSet):
    queryset = Location.objects.all()

    def get_serializer_class(self):
        if self.request.user.is_staff or self.action == 'create':
            return AdminLocationSerializer
        else:
            return UserLocationSerializer

试试吧。让我知道它对你有用。