【问题标题】:Django rest framework nested serializer partial updateDjango rest 框架嵌套序列化程序部分更新
【发布时间】:2015-02-17 15:42:27
【问题描述】:

序列化器:

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 User 模型具有所需的用户名,我想将其设为可选。 有没有办法为此场景启用部分更新?

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

【问题讨论】:

    标签: python django rest frameworks


    【解决方案1】:

    我最终在 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】:

      其实下面的代码已经支持部分更新了:

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

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

      【讨论】:

        【解决方案3】:

        用户序列化器需要更改为类似

        username = fields.CharField(required=False)
        

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            【解决方案5】:

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

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

            【讨论】:

              猜你喜欢
              • 2014-07-19
              • 2021-06-23
              • 1970-01-01
              • 2019-10-13
              • 2019-12-23
              • 2016-05-14
              • 2018-12-13
              • 2016-02-09
              相关资源
              最近更新 更多