2

Is it possible to modify a ViewSet's update() function to update based on a query string parameter instead of a URL resource name or the request body?

For example, I want trigger something like this:

payload = {'field' : '2'}
r = requests.put("http://127.0.0.1:9876/job-defs?job-def-id=2", data=payload)

and have this update my field when job-def-id = 2.

What I have so far is this:

class JobDefinitionsViewSet(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        mixins.UpdateModelMixin,
                        mixins.DestroyModelMixin,
                        viewsets.GenericViewSet):

    serializer_class = JobDefinitionsSerializer

    def update(self, request, pk=None):
        job_def_id = self.request.query_params.get('job-def-id', None)
        super(JobDefinitionsViewSet, self).update(self, request, pk=job_def_id)

    ...
    # other unrelated code
    ...

I'm not too sure how to continue. I want to reuse as much as the update() function from mixins.UpdateModelMixin as possible. Any help is appreciated.

5
  • you seem to be in the right direction. Is it not working? What is the error/log/effect? Commented May 18, 2015 at 21:28
  • Expected view JobDefinitionsViewSet to be called with a URL keyword argument named "pk". Fix your URL conf, or set the .lookup_field attribute on the view correctly. Commented May 18, 2015 at 21:32
  • To fit the API design, I don't want to include the "pk" as a URL resource. This works so far for get : 'list' and post : 'create'. Commented May 18, 2015 at 21:38
  • alright, then you might want to drive the whole thing not through GenericViewSet and its routers/urlconf, but through GenericAPIView Commented May 18, 2015 at 21:43
  • why not override the get_object method so that it uses your pk to fetch the object Commented May 18, 2015 at 22:20

1 Answer 1

1

Assuming you want to use the same url for listing and for retrieving the details of the entity, discriminating on the presence of the url parameter job-def-id, here is a crazy idea:

class JobDefinitionsAllInOneView(mixins.UpdateModelMixin,
                                 mixins.DestroyModelMixin,
                                 mixins.ListModelMixin,
                                 mixins.CreateModelMixin,
                                 generics.GenericAPIView):

    queryset = JobDefinitions.objects.all()
    serializer_class = JobDefinitionsSerializer

    def get_object(self):
        job_def_id = self.request.query_params.get('job-def-id', None)
        if job_def_id is not None:
            self.kwargs['pk'] = job_def_id
        return super(JobDefinitionsAllInOneView, self).get_object()

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        job_def_id = self.request.query_params.get('job-def-id', None)
        if job_def_id is not None:
            # return the details
            return self.retrieve(request, *args, **kwargs)
        else:
            # return a list
            return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

    def patch(self, request, *args, **kwargs):
        return self.partial_update(self, request, *args, **kwargs)
    def delete(self, request, *args, **kwargs):
        return self.destroy(self, request, *args, **kwargs)

I haven't tried it yet. I had a look at the source code here for get_object and here for the mixins

Sign up to request clarification or add additional context in comments.

1 Comment

Very interesting approach. The request is going through but the payload is getting dropped. (PS. there are 2 minor grammatical errors: viewsets.GenericAPIView should be generics.GenericAPIView and self.kwargs['pk'] = self.job_def_id should just be job_def_id)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.