如何在没有路由器的情况下在 Django Rest Framework (DRF) RetrieveUpdateDestroyAPIView 中嵌套 URL 路由

How to Nest URL routes in Django Rest Framework (DRF) RetrieveUpdateDestroyAPIView without router

我正在使用 Django rest 框架和 RetrieveUpdateDestroyAPIView 并尝试实现嵌套 URL 模式。

# my current URLs structure is like
/api/v1/kitchens/ - ListCreateAPIView
/api/v1/kitchens/1/ - RetrieveUpdateDestroyAPIView
/api/v1/orders/ - ListCreateAPIView
/api/v1/orders/1/ - RetrieveUpdateDestroyAPIView
/api/v1/items/ - ListCreateAPIView
/api/v1/items/1/ - RetrieveUpdateDestroyAPIView

以上结构适用于所有操作,但要获取单个厨房下的物品或订单列表,我正在尝试实现以下内容。

views.py 有如下内容。

class KitchenListView(generics.ListCreateAPIView):
  queryset = Kitchen.objects.all()
  serializer_class = KitchenSerializer
  pagination_class = LimitOffsetPagination
  permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
  authentication_classes = (TokenAuthentication,)
  filter_backends = (DjangoFilterBackend,)
  filter_fields = ("user",)


class KitchenDetailView(generics.RetrieveUpdateDestroyAPIView):
  queryset = Kitchen.objects.all()
  serializer_class = KitchenDetailsSerializer
  permission_classes = (
    permissions.IsAuthenticatedOrReadOnly,
    IsOwnerOrReadOnly,
  )
 authentication_classes = (TokenAuthentication,)

# I want to create this structure.
/api/v1/kitchens/ - List
/api/v1/kitchens/1/ - Details
/api/v1/kitchens/1/orders/ - Orders List
/api/v1/kitchens/1/orders/1/ - Order Details
/api/v1/kitchens/1/items/ - Items List
/api/v1/kitchens/1/items/1/ - Item Details

我正在努力实现这样的目标。请向我建议更好的解决方案(如果有人有的话)以及使用通用 API 视图或视图集会更好,因为我的项目是一个大型项目。

提前致谢。

首先,我假设您有订单视图和商品视图;在你的两个观点中试试这个:

from rest_framework.generics import get_object_or_404


class OrderListView(generics.ListCreateAPIView):
    ...
   
    def get_queryset(self):
        if self.kwargs.get('kitchen_pk'):
            return self.queryset.filter(kitchen_id=self.kwargs.get('kitchen_pk'))
        return self.queryset.all()

class OrderDetailView(generics.RetrieveUpdateDestroyAPIView):
    ...

    def get_object(self):
        if self.kwargs.get('kitchen_pk'):
            return get_object_or_404(self.get_queryset(), kitchen_id=self.kwargs.get('kitchen_pk'), pk=self.kwargs.get('order_pk')) 
        return get_object_or_404(self.get_queryset(), pk=self.kwargs.get('order_pk'))


class ItemListView(generics.ListCreateAPIView):
    ...
   
    def get_queryset(self):
        if self.kwargs.get('kitchen_pk'):
            return self.queryset.filter(kitchen_id=self.kwargs.get('kitchen_pk'))
        return self.queryset.all()

class ItemDetailView(generics.RetrieveUpdateDestroyAPIView):
    ...

    def get_object(self):
        if self.kwargs.get('kitchen_pk'):
            return get_object_or_404(self.get_queryset(), kitchen_id=self.kwargs.get('kitchen_pk'), pk=self.kwargs.get('item_pk'))  
        return get_object_or_404(self.get_queryset(), pk=self.kwargs.get('item_pk'))
       

在你的urls.py中:

urlpatterns = [
    path('kitchens/', KitchenListView.as_view(), name='kitchens'),
    path('kitchens/<int:pk>/', KitchenDetailView.as_view(), name='kitchen'),

    path('kitchens/<int:kitchen_pk>/orders/', OrderListView.as_view(), name='kitchen_orders'),
    path('kitchens/<int:kitchen_pk>/orders/<int:order_pk>/', OrderDetailView.as_view(), name='kitchen_order'),

    path('kitchens/<int:kitchen_pk>/items/', ItemListView.as_view(), name='kitchen_items'),
    path('kitchens/<int:kitchen_pk>/items/<int:item_pk>/', ItemDetailView.as_view(), name='kitchen_item'),
]

我不知道它是否有效,但这是一个开始!