Django Rest Framework 中嵌套 URL 的相关资源
Related resources on a nested URL in Django Rest Framework
我有两个模型,Foo
和 Bar
。 Bar
有一个指向 Foo
的外键。我有一个 Foo
的 ModelViewSet
,我想要路由 /api/foos/<pk>/bars/
到 return 所有与给定 foo
相关的 bar
。
我知道这可以通过操作来完成。例如
class FooViewSet(viewsets.ModelViewSet):
serializer_class = FooSerializer
queryset = Foo.objects.all()
@action(detail=True, methods=['GET'])
def bars(self, request, pk):
queryset = Bar.objects.filter(foo=pk)
serializer = BarSerializer(queryset, many=True)
return Response(serializer.data)
@bars.mapping.post
def create_bar(self, request, pk):
request.data['foo'] = pk
serializer = BarSerializer(request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
然而,这感觉像是很多不必要的样板代码。
不幸的是,使用 bars = PrimaryKeyRelatedField(many=True)
不适合我的情况,因为每个 foo
可以有数百个 bars
,我不想在每个请求中发送。
是否可以更方便地在视图集中执行此操作?如果不是,正常的 DRF 方法是什么?具有不同 URL 的解决方案对我来说也是可以接受的,只要它最大限度地减少样板代码。
对我来说最直接的解决方案是对这个特定端点使用一个简单的 generics.ListAPIView
:
views.py
from rest_framework import generics
class FooBarsListAPIView(generics.ListAPIView):
serializer_class = BarSerializer
def get_queryset(self):
return Bar.objects.filter(foo=self.kwargs.get('pk'))
然后您只需在 urls.py
而不是视图集中注册此视图。
为了达到您想要的结果,您需要做的就是这些。您只需指定查询集过滤器的外观,其他一切都由 ListAPIView
实现完成。
视图集在大多数情况下都可以完成工作,但如果您想要像这样的特定内容,视图集可能会变得矫枉过正。
是的,现在为这个特定端点定义了一个额外的 class,但样板代码减少到零,这正是我们最终想要的。
我有两个模型,Foo
和 Bar
。 Bar
有一个指向 Foo
的外键。我有一个 Foo
的 ModelViewSet
,我想要路由 /api/foos/<pk>/bars/
到 return 所有与给定 foo
相关的 bar
。
我知道这可以通过操作来完成。例如
class FooViewSet(viewsets.ModelViewSet):
serializer_class = FooSerializer
queryset = Foo.objects.all()
@action(detail=True, methods=['GET'])
def bars(self, request, pk):
queryset = Bar.objects.filter(foo=pk)
serializer = BarSerializer(queryset, many=True)
return Response(serializer.data)
@bars.mapping.post
def create_bar(self, request, pk):
request.data['foo'] = pk
serializer = BarSerializer(request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
然而,这感觉像是很多不必要的样板代码。
不幸的是,使用 bars = PrimaryKeyRelatedField(many=True)
不适合我的情况,因为每个 foo
可以有数百个 bars
,我不想在每个请求中发送。
是否可以更方便地在视图集中执行此操作?如果不是,正常的 DRF 方法是什么?具有不同 URL 的解决方案对我来说也是可以接受的,只要它最大限度地减少样板代码。
对我来说最直接的解决方案是对这个特定端点使用一个简单的 generics.ListAPIView
:
views.py
from rest_framework import generics
class FooBarsListAPIView(generics.ListAPIView):
serializer_class = BarSerializer
def get_queryset(self):
return Bar.objects.filter(foo=self.kwargs.get('pk'))
然后您只需在 urls.py
而不是视图集中注册此视图。
为了达到您想要的结果,您需要做的就是这些。您只需指定查询集过滤器的外观,其他一切都由 ListAPIView
实现完成。
视图集在大多数情况下都可以完成工作,但如果您想要像这样的特定内容,视图集可能会变得矫枉过正。 是的,现在为这个特定端点定义了一个额外的 class,但样板代码减少到零,这正是我们最终想要的。