There are 2 HTTP Request Methods to update the data:
PUT
The PUT method requests that the enclosed entity be stored under the supplied
URI. If the URI refers to an already existing resource, it is modified; if the
URI does not point to an existing resource, then the server can create the
resource with that URI.
PATCH
The PATCH method applies partial modifications to a resource.
As we can see PUT updates the every resource of entire data, whereas PATCH
updates the partial of data.
In other words: We can say PUTreplace where PATCHmodify.
So in this article we are going to look for PATCH
method.
Let’s assume you have a simple ModelViewSet for your Django Rest Framework,
and you want to allow users to update partial data field(s) of this model. How
can you achieve that?
After some lookup for the doc and core of DRF I found that
ModelViewSet inherits some Mixinsparent classes and you have to
override default partialkwargs in UpdateModelMixin.
# https://github.com/encode/django-rest-framework/blob/91916a4db1/rest_framework/viewsets.pyclassModelViewSet(mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet):"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""pass
# https://github.com/encode/django-rest-framework/blob/91916a4db14cd6a06aca13fb9a46fc667f6c0682/rest_framework/mixins.py#L64classUpdateModelMixin:"""
Update a model instance.
"""defupdate(self,request,*args,**kwargs):partial=kwargs.pop('partial',False)instance=self.get_object()serializer=self.get_serializer(instance,data=request.data,partial=partial)serializer.is_valid(raise_exception=True)self.perform_update(serializer)ifgetattr(instance,'_prefetched_objects_cache',None):# If 'prefetch_related' has been applied to a queryset, we need to# forcibly invalidate the prefetch cache on the instance.instance._prefetched_objects_cache={}returnResponse(serializer.data)defperform_update(self,serializer):serializer.save()defpartial_update(self,request,*args,**kwargs):kwargs['partial']=Truereturnself.update(request,*args,**kwargs)
Solution
So you simply override update function like below:
classTask(BaseModelMixin):STATES=(("todo","Todo"),("wip","Work in Progress"),("suspended","Suspended"),("waiting","Waiting"),("done","Done"),)title=models.CharField(max_length=255,blank=False,unique=True)description=models.TextField()status=models.CharField(max_length=15,choices=STATES,default="todo")tag=models.ForeignKey(to=Tag,on_delete=models.DO_NOTHING)category=models.ForeignKey(to=Category,on_delete=models.DO_NOTHING)classMeta:ordering=("title",)def__str__(self):returnf"{self.created_by}:{self.title}"