Home > OS >  how you can handle 2 different types of arguments with only one view in django rest framework?
how you can handle 2 different types of arguments with only one view in django rest framework?

Time:10-06

I have urls.py looks like below

urlpatterns = [
    path("watch-list/<int:pk>/", views.WatchItemDetail.as_view(), name="watch-detail"),
    path("watch-list/<str:slug>/", views.WatchItemDetail.as_view(), name="watch-detail-slug"),
]

so i am sending 2 different type of arguments in same path one is pk and it can also be slug.

In my views.py I am writing 2 get request I know this will not work since python not support overloding of methods so how can i achieve like below logic? can we clean up some code also because i am repeating my self with same logic.

class WatchItemDetail(APIView):

    def get(self, request, pk):
        watch_item = get_object_or_404(WatchItem, pk=pk)
        watch_item_serializer = WatchItemSerializer(watch_item)
        return Response(watch_item_serializer.data, status=status.HTTP_200_OK)

    def get(self, request, slug):
        watch_item = get_object_or_404(WatchItem, slug=slug)
        watch_item_serializer = WatchItemSerializer(watch_item)
        return Response(watch_item_serializer.data, status=status.HTTP_200_OK)

This will work only for slug field because previous method is overwritten by next one but i want both of them to work.

CodePudding user response:

You can simply try this:

class WatchItemDetail(APIView):

    def get(self, request, value):
        watch_item = get_object_or_404(WatchItem, pk=value) if isinstance(value, int) else get_object_or_404(WatchItem, slug=value)
        watch_item_serializer = WatchItemSerializer(watch_item)
        return Response(watch_item_serializer.data, status=status.HTTP_200_OK)

CodePudding user response:

You can check the type and work accordingly:

class WatchItemDetail(APIView):

    def get(self, request, item):
        watch_item = get_object_or_404(WatchItem, pk=item) if isinstance(item, int) else get_object_or_404(WatchItem, slug=item)
        watch_item_serializer = WatchItemSerializer(watch_item)
        return Response(watch_item_serializer.data, status=status.HTTP_200_OK)

CodePudding user response:

Another way is to also capture both pk and slug kwargs like this:

from django.http import Http404


class WatchItemDetail(APIView):

    def get(self, request, pk=None, slug=None, *args, **kwargs):
        if pk is None:
            watch_item = get_object_or_404(WatchItem, pk=pk)
        elif slug is None:
            watch_item = get_object_or_404(WatchItem, slug=slug)
        else:
            raise Http404(f'No {WatchItem._meta.object_name} matches the given query.')

        watch_item_serializer = WatchItemSerializer(watch_item)
        return Response(watch_item_serializer.data, status=status.HTTP_200_OK)
  • Related