繁体   English   中英

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

[英]Django rest framework nested serializer partial update

序列化器:

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,)

create 和 update 都工作得很好,问题在于部分更新。 django 用户模型具有必需的用户名,我想将其设为可选。 有没有办法为这种情况启用部分更新?

例如,我想用 PUT 更新“foo”。

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

我个人认为它的工作原理有点奇怪,PUT 需要所有非可选参数,但会单独保留可选参数。 因此,您可以编辑可选参数,同时保留其他可选参数,但不能对必需参数执行相同操作(我的意思是您显然可以只提供现有值,但是如果它们在您编辑时发生更改,您就被搞砸了,将强制更改它们背部)。 PATCH 对我来说更有意义。 你提供的任何论点都会改变,你不提供的任何论点都不会。 IMO PUT 应该清除未提供的任何可选参数,以便它是真正的替换而不是简单的替换必需和更新 (PUT) 可选。

我最终在 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。 不确定这是否是最优雅的解决方案,但它有效。 如果有人有更好的解决方案,请分享:)

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

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

这个' get ' 函数将从validated_data 中获取'username'字段。 如果它不存在,则将返回 instance.username。

用户序列号需要更改为类似

username = fields.CharField(required=False)

我认为在serializers.py 中定义和覆盖update()方法时强制执行partial=True就足够了,即:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM