Как можно обрабатывать 2 разных типа аргументов с помощью одного представления в django rest framework?

У меня urls.py выглядит как показано ниже

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"),
]

Итак, я отправляю 2 различных типа аргументов по одному и тому же пути, один из которых pk, а другой может быть slug.

В моем views.py я пишу 2 get запроса я знаю, что это не будет работать, так как python не поддерживает оверлодинг методов, поэтому как я могу достичь как ниже логики? Мы можем очистить некоторый код также, потому что я повторяю себя с той же логикой.

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)

Это будет работать только для поля slug, потому что предыдущий метод перезаписывается следующим, но я хочу, чтобы работали оба.

Вы можете проверить тип и работать соответствующим образом:

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)

Вы можете просто попробовать следующее:

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)

Другой способ состоит в том, чтобы также захватить оба pk и slug kwargs следующим образом:

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)
Вернуться на верх