Django Rest Framework 中嵌套 URL 的相关资源
Posted
技术标签:
【中文标题】Django Rest Framework 中嵌套 URL 的相关资源【英文标题】:Related resources on a nested URL in Django Rest Framework 【发布时间】:2019-12-23 14:12:30 【问题描述】:我有两个模型,Foo
和 Bar
。 Bar
有一个指向 Foo
的外键。我有一个用于Foo
的ModelViewSet
,我希望路由/api/foos/<pk>/bars/
返回与给定foo
相关的所有bar
s。
我知道这可以通过操作来完成。例如
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 的解决方案。
【问题讨论】:
【参考方案1】:对我来说,直接的解决方案是为此特定端点使用简单的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
实现完成。
在大多数情况下,视图集都在发挥作用,但如果您想要这样的特定内容,视图集可能会变得过大。 是的,现在为这个特定的端点定义了一个额外的类,但是样板代码减少到零,这是我们最终想要的。
【讨论】:
以上是关于Django Rest Framework 中嵌套 URL 的相关资源的主要内容,如果未能解决你的问题,请参考以下文章
需要 Django Rest Framework 嵌套序列化程序 = False 错误
在 Django REST Framework 中处理嵌套对象表示
Django REST Framework:在嵌套对象中定义字段?
django-rest-framework、多表模型继承、ModelSerializers 和嵌套序列化器