I have a Django Rest Framework set up that serves GET requests properly. After asking a previous question here, it should also be able to update objects properly. However, I'm not sure how I can update just one field in a model object. I have a Model ViewSet like this:

class TaskViewSet(viewsets.ModelViewSet):
    queryset = Task.objects.filter(done = False).order_by('-unixTime')
    serializer_class = TaskSerializer
    paginate_by = None

And I have the urls registered through a router like this:

router = routers.DefaultRouter()
router.register(task', views.TaskViewSet)
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

The serializer is about as basic as they come right now:

class TaskSerializer(serializers.ModelSerializer):

    class Meta:
        model = Task
        fields = ('id', 'user', 'task', 'unixTime', 'done')

I'd like to be able to update the 'done' field of the Task object as identified by its primary-key id. I think I would need to use a partial_update model or path, but I'm unsure how to implement this. Also, just to give more information, the DRF browser view says the allowed HTTP methods are GET, POST, HEAD, OPTIONS.

1 Answer 1

If you are using a ModelViewSet, just add put to your url's as_view() parameter.

You should have something like this in your url:

  TaskViewSet.asView({'get': 'retrieve', 'put': 'update'})

i.e:

  url(r'^your-regex$', TaskViewSet.asView({'get': 'retrieve', 'put': 'update'}), name='whatever')

You can then use requests.put to update it.

If you'd want to override the update method, you can add these to your ViewSet:

      def update(self, request, *args, **kwargs):
            # Perform your custom actions here and probably call:
            super(TechyRetrieveUpdate, self).update(request, *args, **kwargs)