如何在 django rest 框架中仅用一个视图处理 2 种不同类型的参数?
how you can handle 2 different types of arguments with only one view in 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 not None:
watch_item = get_object_or_404(WatchItem, pk=pk)
elif slug is not 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)
我有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 not None:
watch_item = get_object_or_404(WatchItem, pk=pk)
elif slug is not 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)