Search code examples
djangodjango-rest-framework

Calling the create method of a ModelViewSet from another ModelViewSet


I need to create objects of model B from the views.py file of A. I was able to do it using the serialiser of B (see # OLD METHOD using serializer) but I would like to know how to use the create method of viewset B from viewset A

In the function generate_drf_format, I tried to manually instantiate and invoke the create action in Viewset B but it's not working. I am getting the error message:

AttributeError: 'ViewSetB' object has no attribute 'request'

class ViewSetB(viewsets.ModelViewSet):
    queryset = B.objects.all()
    serializer_class = BSerializer



 class ViewSetA(viewsets.ModelViewSet):
     queryset = A.objects.all()
     serializer_class = ASerializer
 
     def create(self, request, *args, **kwargs):
         form_data = request.data
 
         # map front-end request to DRF model
         mapped_data = generate_drf_format(form_data)
 
         serializer = self.get_serializer(data=mapped_data)
         serializer.is_valid(raise_exception=True)
         self.perform_create(serializer)
         headers = self.get_success_headers(serializer.data)
         return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)




def generate_drf_format(form_data):
    participants_ids = []
    if 'participants' in form_data:
        participants_list = form_data['participants']

        if len(participants_list) > 0:
            request = HttpRequest()
            for participant_data in participants_list:
                    request.data = participant_data

                    # Manually instantiate and invoke action in Viewset B
                    viewset_b = UserViewSet()
                    viewset_b.create(request=request)

                    # OLD METHOD using serializer
                    # b_serializer = BSerializer(data=participant_data)
                    # if b_serializer.is_valid():
                    #     b_serializer.save()
                    #     participants_ids.append(b_serializer.data['id'])
                    # else:
                    #     return Response(b_serializer.errors)

    new_data = generate_some_obj(form_data, participants_ids)
    return new_data

Any suggestion of how to call the create method of one viewset from another viewset


Solution

  • The method handlers for a class ViewSet are only bound to the corresponding actions at the point of finalizing the view, using the .as_view() method.

    Hence to manually call a method handler of a class ViewSet, you must first finalize the class ViewSet.

    viewset_b = ViewSetB.as_view({"post": "create"})
    viewset_b(request=request) #[1]

    [1] Ensure that the request object is completely instantiated and will not cause a permission error, method not allowed error or any other type of error.