DRF - Base Viewset for query param validation
Asked Answered
N

1

3

I am using Django 1.9 and Django Rest Framework 3.3

I'm creating three new endpoints that are similar but still different enough that I want them to be their own viewsets to avoid messy code. They are not backed by a model so I am extending ViewSet directly. One similarity between all three endpoints is they require the same two query parameters. So I find I am doing this:

class MyFirstViewset(viewsets.ViewSet):

    def list(self, request):
        some_param = request.query_params.get('someparam')
        if not some_param:
            return Response('someparam query parameter is required', status.HTTP_400_BAD_REQUEST)
        some_other_param = request.query_params.get('someotherparam')
        if not some_other_param:
              return Response('someotherparam query parameter is required', status.HTTP_400_BAD_REQUEST)


class MySecondViewset(viewsets.ViewSet):

    def list(self, request):
        some_param = request.query_params.get('someparam')
        if not some_param:
            return Response('someparam query parameter is required', status.HTTP_400_BAD_REQUEST)
        some_other_param = request.query_params.get('someotherparam')
        if not some_other_param:
              return Response('someotherparam query parameter is required', status.HTTP_400_BAD_REQUEST)

As you can see... it's not very DRY. An obvious solution would be inheritance with a base viewset doing the similar parts of validation, the problem is I'm not sure what the best practice is for doing something like this with DRF. Would I want to make a protected access validation function and call that? But if all I was doing was checking a dict for keys it wouldn't even have to be in a ViewSet right? Just having the last class do the validation in list() then calling that in all the child viewsets also seems odd to me since then I am using list() to validate and not actually return anything in the base class.

Could anyone tell me what a good approach to this would be? What's best practice for cases like this? I Googled around but couldn't find anything. Any advice would be appreciated. Thanks!

Neal answered 8/4, 2016 at 17:27 Comment(0)
O
3

One reason for why Class Base class are better is exactly that you can add your own derivation or at least add MixIns, so from the pure coding point of view, I think you should just add your own MyBaseViewSet and have MyFirstViewset and MySecondViewset derive from it.

That said, consider overwriting get_queryset instead of list, and use ListAPIView so you get some default behavior, and just return an empty array or if you really want to return an error, through an exception:

class MyBaseViewSet(generics.ListAPIView):
    serializer_class = YourSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def get_queryset(self):
        some_param = self.request.query_params.get('someparam')
        if not some_param:
             raise exceptions.PermissionDenied
Oech answered 9/4, 2016 at 0:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.