11

Here are my simple viewset and serializer classes:

class UserSerializer(ModelSerializer):

    class Meta:
        model = User
        fields = ['id', 'email', 'first_name', 'last_name']

....    

class UserViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

Suppose I want to update only my user's first name. In that case, I should use PATCH {"first_name": "New First Name"}. But at the same time, it looks like that PUT {"first_name": "New First Name"} also works the same way, though it shouldn't, because it has to validate that all the fields are specified. At least I thought so. Am I wrong? And if I'm, then what is the difference between update and partial_update in Django Rest Framework and is there any reason to keep them both (since any additional method implies additional testing, so the latter question is a bit philosophical, because looks like people find this PUT/PATCH pair really confusing). By the way, I'm using djangorestframework==3.8.2. Thank you.

Gevorg Davoian
  • 484
  • 5
  • 13

1 Answers1

10

If you look at the generated serializer, you'll find that you don't have required fields. In that case, PUT and PATCH will have similar behavior. Would there be any required field, you'd see the difference.

serializer = UserSerializer(instance=user, data={"first_name": "New First"})
print(serializer)                                                                                                                                                                                  

    UserSerializer(data={'first_name': 'New First'}, instance=<User: tester>):
        id = IntegerField(label='ID', read_only=True)
        email = EmailField(allow_blank=True, label='Email address', max_length=254, required=False)
        first_name = CharField(allow_blank=True, max_length=30, required=False)
        last_name = CharField(allow_blank=True, max_length=150, required=False)
Linovia
  • 19,812
  • 4
  • 47
  • 48
  • Hm, but according to the documentation, all fields are `required=True` by default. – Gevorg Davoian Oct 31 '18 at 11:33
  • 2
    When you explicitly define them without providing an explicite `required=False`. For autogenerated fields from a model, things are a bit different. – Linovia Oct 31 '18 at 13:18
  • 1
    This is implemented at https://github.com/encode/django-rest-framework/blob/master/rest_framework/utils/field_mapping.py#L100-L101 – Linovia Oct 31 '18 at 13:22
  • The file @Linovia was pointing to has changed, here is a permalink to the right place: https://github.com/encode/django-rest-framework/blob/c5d9144aef1144825942ddffe0a6af23102ef44a/rest_framework/utils/field_mapping.py#L104-L105 – Julien Palard Aug 30 '21 at 08:29