使用Django Rest Framework将相关对象作为单独的端点(“边缘”模型)

时间:2017-05-16 23:36:46

标签: django django-rest-framework

更新:某些第三方软件包(drf-nested-routersdrf-extensions)似乎已解决此问题。有没有简单的方法用香草DRF做到这一点?

背景

我正在试图弄清楚如何构建一个API,其中端点可以有额外的“边缘”,可用于查找相关对象,而不是在“端点”中包含那些相关对象(或它们的pks)。掌握“对象本身。当存在 lot 相关对象时,这可能很方便,因为在主对象的响应中包含相关对象会很昂贵。

这种API风格的一些例子是GitHub API和Facebook Graph API:

/repos/:owner/:repo/issues =>获取与 repo

相关的问题列表

/v2.9/{photo-id}/likes =>获取与照片

相关的列表

实施例

在下面的设计示例中,我认为list_route中的ViewSet可用于构建此类关系,但它会创建/repos/issues/形式的网址而不是/repos/{pk}/issues/。如果我将其更改为detail_route,则会在网址中留下{pk},但这似乎是对detail_route的滥用,因为这真的是要返回单个对象,对吗?

class Repo(models.Model):
    name = models.TextField()


class Issue(models.Model):
    title = models.TextField()
    body = models.TextField()
    repo = models.ForeignKey(Repo)


class RepoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Repo
        fields = ('pk', 'name')
        # don't want to include all issues here, there might be a lot.


class IssueSerializer(serializers.ModelSerializer):
    class Meta:
        model = Issue
        fields = ('pk', 'title', 'body')


class RepoViewSet(viewsets.ModelViewSet):
    serializer_class = RepoSerializer

    # THIS DOESN'T WORK!  It creates:
    # /repos/issues/ rather than /repos/{pk}/issues/
    @list_route(serializer_class=IssueSerializer)
    def issues(self):
        repo = self.get_object()
        issues = repo.issue_set.all()
        s = self.get_serializer(issues, many=True)
        return Response(s.data)


router.register(r'repos', RepoViewSet, base_name='repos')

我有什么想法可以从这个人那里获得/repos/{pk}/issues/网址吗?

1 个答案:

答案 0 :(得分:1)

没有理由detail_route只返回单个实例,detail_route是一个实例(详细信息视图)上的路由,但可能会返回相对于该实例的列表。

查看DRF docs的第二个示例:detail_route装饰器用于返回列表。