在我的REST API中,我有两个实体:Test
和TestRun
。我希望能够发送POST请求以创建TestRun
(包含相应的TestRun
字段),但此请求的网址必须为api/v1/test/{id}/start
而不是api/v1/testrun
。
我知道使用@detail_route
我可以自定义网址,但请求仍然会发送到api/v1/test/{id}
:
class TestViewSet(viewsets.ModelViewSet):
queryset = Test.objects.all()
serializer_class = TestSerializer
@detail_route(methods=['post'], url_path='start')
def start_test(self, request, pk=None):
pass
class TestRunViewSet(viewsets.ModelViewSet):
queryset = TestRun.objects.all()
serializer_class = TestRunSerializer
这里可能需要一些高度定制的路由器?
答案 0 :(得分:1)
好的,我有基本的例子。我认为你几乎没有问题,所以首先要做的事情是:
我的观点:
class TestViewSet(viewsets.ModelViewSet):
queryset = Test.objects.all()
serializer_class = TestSerializer
@detail_route(methods=['post'], url_path='start', serializer_class=TestRunSerializer)
def start_test(self, request, pk=None):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
# add here TestRun object
return Response(serializer.data, status=status.HTTP_200_OK)
class TestRunViewSet(viewsets.ModelViewSet):
queryset = TestRun.objects.all()
serializer_class = TestRunSerializer
我的网址:
router = SimpleRouter()
router.register('test', TestViewSet)
router.register('test-run', TestRunViewSet)
urlpatterns = router.urls
和设置网址:
urlpatterns = [
url(r'^api/v1/', include('droute.urls'))
]
在这种情况下,您拥有Test和TestRun模型的完整CRUD - 一个在api / vi / test下,第二个在api / v1 / test-run中;
detail_route装饰器为您创建了额外的路线:/ api / v1 / test /:id / start
但这并不意味着api / v1 / test-run下的CRUD不再可访问。
如果你不想在api / v1 / test-run上不允许创建,你应该使用ReadOnlyModelViewSet作为TestRunViewSet的基础 - 这将只允许列表端点上的GET:api / v1 / test-run和在详细信息端点上:api / v1 / test-run //
你不需要在路由器中制造魔法 - 例如,SimpleRouter足以满足这种情况。
如果你想制作嵌套路由器,事情会变得更加复杂。你可以搜索stackoverflow - 有很多关于它的文章。但说实话,我会阻止你使用嵌套路由器,我从来没有觉得使用这是一种乐趣:)你可以在这里查看: https://github.com/alanjds/drf-nested-routers
我认为(但我有很少或没有信息),最好的API就是这样:
快乐的编码,希望这有帮助。