1

I'm trying to do a REST in Django using the VIEWSETS library. I created a Container model that works well. Container is associated with the ContainerModerator model. The endpoint should be:

POST containers/{container_id}/moderators

One of the fields in ContainerModerator is container_id. I would like to get it from the path.

Below is what I have now. I tried in different ways to get there. I also read similar posts, usually for a library other than VIEWSETS. I am a beginner and I wonder if there is a simple, elegant solution for this case that will be easy for me to understand? Should I use other libraries like APIVIEW or GenericAPIView?

models:

class ContainerModerator(models.Model):
  moderator_id = models.ForeignKey(settings.AUTH_USER_MODEL, 
                 on_delete=models.CASCADE)
  container_id = models.ForeignKey(Container, on_delete=models.CASCADE)

serializers:

class ContainerModeratorSerializer(serializers.ModelSerializer):

  class Meta:
    model = models.ContainerModerator
    fields = '__all__'

views:

class ContainerModeratorViewSet(viewsets.ModelViewSet):
  serializer_class = serializers.ContainerModeratorSerializer
  queryset = models.ContainerModerator.objects.all()

  def perform_create(self, serializer):
    serializer.save()

urls:

router.register('v1/containers/<int:container_id>/moderators', 
views.ContainerModeratorViewSet)

urlpatterns = [
  path('', include(router.urls))
]
Alasdair
  • 298,606
  • 55
  • 578
  • 516
Jacek Tessen
  • 43
  • 1
  • 7

2 Answers2

3

You can get the container_id from self.kwargs['container_id'] and search Container instance with container_id. Particularly you need something like this in your viewset:

class ContainerModeratorViewSet(viewsets.ModelViewSet):
     serializer_class = serializers.ContainerModeratorSerializer
     queryset = models.ContainerModerator.objects.all()

     def get_object(self):
         #Override this method to get your cantainer instance
         return get_object_or_404(Container, id=self.kwargs['pk']) 

     def post(self, request, *args, **kwargs)):

        instance = self.get_object()
        data = {
           container : instance.id,
           moderator : request.user
        }

        return self.create(data)

    def create(self, data):
       serializer = self.get_serializer(data=data)

       self.permform_create(serializer)
       return Response(serializer.data)

    def perform_create(self, serializer):
        serializer.save()

Just read the source code of GenericAPIView, ModelViewSet and ViewMixins carefully to see how it connect to each other.

Silasi
  • 129
  • 2
  • 10
0

You can do this from the simply by using self.get_object() method which is available under RetrieveModelMixin

Here is the implementation of RetrieveModelMixin,

def retrieve(self, request, *args, **kwargs):
    instance = self.get_object()
    serializer = self.get_serializer(instance)
    return Response(serializer.data)

The ModelViewSet class inherits from GenericAPIView and includes implementations for various actions, by mixing in the behavior of the various mixin classes.

The actions provided by the ModelViewSet class are .list(), .retrieve(), .create(), .update(), .partial_update(), and .destroy().

https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset