Django休息框架嵌套序列化器部分更新

时间:2014-12-18 18:47:15

标签: python django rest frameworks

串行器:

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserProfile
        fields = ('foo', 'bar')


class UserSerializer(serializers.ModelSerializer):
    userprofile = ProfileSerializer(partial=True)

    class Meta:
        model = User
        fields = ('username', 'password', 'email', 'userprofile')

    def create(self, validated_data):
        profile_data = validated_data.pop('userprofile')
        user = User.objects.create(**validated_data)
        UserProfile.objects.create(user=user, **profile_data)

        return user

    def update(self, instance, validated_data):
        profile_data = validated_data.pop('userprofile')
        profile = instance.userprofile

        instance.username = validated_data.get('username', instance.username)
        instance.email = validated_data.get('email', instance.email)
        instance.save()

        profile.foo = profile_data.get('foo', profile.foo)
        profile.bar = profile_data.get('bar', profile.bar)
        profile.save()

        return instance

查看:

class UsersViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

创建和更新都运行得很好,问题在于部分更新。 django用户模型具有所需的用户名,我想使其成为可选项。 有没有办法为这种情况启用部分更新?

例如,我想用PUT更新" foo"。

5 个答案:

答案 0 :(得分:6)

默认情况下,PUT应提供所有必需的参数。但PATCH不是。因此,只要您使用PATCH而不是PUT就可以了,您根本不必更改代码。

我个人认为这有点奇怪,PUT要求所有参数都不是可选的,但会单独留下可选参数。所以你可以编辑可选参数,同时只留下其他可选参数,但不能用必需的参数做同样的事情(我的意思是你显然可以只提供现有的值,但是如果你在编辑时它们发生了变化,你就会被搞砸了改回来)。 PATCH对我来说更有意义。您提供的任何争论都将被更改,而您所提供的任何争论都不会被取消。 IMO PUT应该删除任何未提供的可选参数,以便它是一个真正的替换,而不是简单的替换需要和更新(PUT)可选。

答案 1 :(得分:4)

我最终覆盖了UsersViewSet中的get_serializer:

    def get_serializer(self, instance=None, data=None, many=False, partial=False):
        """If request is not PUT, allow partial updates."""
        if self.request.method == 'PUT':
            return UserSerializer(instance=instance, data=data, many=many, partial=True)
        else:
            return UserSerializer(instance=instance, data=data, many=many, partial=partial)

如果request.method是PUT,则强制部分为True。不确定这是否是最优雅的解决方案,但它确实有效。 如果任何人有更好的解决方案,请分享:)

答案 2 :(得分:1)

实际上,以下代码已经支持部分更新:

instance.username = validated_data.get('username', instance.username)

获取'功能将从 validated_data 获取'用户名'字段。如果它不存在,则返回instance.username。

答案 3 :(得分:1)

用户seriliazer需要改为

username = fields.CharField(required=False)

答案 4 :(得分:0)

我认为在 serializers.py 中定义和覆盖partial=True方法时,只需执行update(),即:

def update(self, instance, validated_data, partial=True):
...