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 【问题描述】:

我有两个模型,FooBarBar 有一个指向 Foo 的外键。我有一个用于FooModelViewSet,我希望路由/api/foos/<pk>/bars/ 返回与给定foo 相关的所有bars。

我知道这可以通过操作来完成。例如

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 和嵌套序列化器

在 Django Rest Framework 中正确更新嵌套序列化程序

Django Rest Framework 中嵌套序列化程序的唯一验证