Django Rest Framework update field

2020-02-08 05:30发布

问题:

I am new to DRF and I am trying to write custom view / serializer that I can use to update just one field of user object.

I need to make logic just to update the "name" of the user.

I wrote serializer:

class ClientNameSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClientUser
        fields = ('name',)

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.save()
        return instance

This method is never called. I tried setting breakpoint there and debug it, but it is never called, even if I use PUT, POST or PATCH methods. If I add create method it is being called when I use POST.

This is how my view looks like:

class UpdateName(generics.CreateAPIView):
    queryset = ClientUser.objects.all()
    serializer_class = ClientNameSerializer
    permission_classes = (permissions.IsAuthenticated,)

Does anyone have some suggestion? Thanks!

My models.py looks like this

class ClientUser(models.Model):
    owner = models.OneToOneField(User,unique=True,primary_key=True)

    phone_number = models.CharField(validators=[PHONE_REGEX],max_length=20,unique=True)

    name = models.CharField(max_length=100,blank=True)
    status = models.IntegerField(default=1)
    member_from = models.DateTimeField('member from',auto_now_add=True)
    is_member = models.BooleanField(default=False)

回答1:

The definition of what methods the endpoint can accept are done in the view, not in the serializer.

The update method you have under your serializer needs to be moved into your view so you'll have something like:

serializers.py

class ClientNameSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClientUser

views.py

class UpdateName(generics.UpdateAPIView):
    queryset = ClientUser.objects.all()
    serializer_class = ClientNameSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.name = request.data.get("name")
        instance.save()

        serializer = self.get_serializer(instance)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        return Response(serializer.data)

Take note that you're overriding the UpdateModelMixin and you might need to change the above code a little bit to get it right.



回答2:

If you use class UpdateName(generics.CreateAPIView), this will only call a create() method on the serializer.

You should subclass generics.UpdateAPIView instead. And that's it. You do not have to move your method to the view as suggested in this answer (it is basically copying/duplicating the UpdateModelMixin's update method)

For more information how serializers work regarding saving/updating see the docs here: