在Django Rest Framework中添加特定的方法处理程序detail_route

War*_*ick 3 python django django-rest-framework

我有一个使用Django Rest Framework构建的API.有一个ViewSet在它detail_route了,我就是想用处理嵌套数据:

from rest_framework.mixins import (RetrieveModelMixin, CreateModelMixin, 
                                   ListModelMixin)
from rest_framework.viewsets import GenericViewSet

class UserViewSet(RetrieveModelMixin, CreateModelMixin, ListModelMixin, 
                  GenericViewSet)

    ...

    @detail_route(methods=['get'], url_path='photos')
    def photos(self, request):
        return Response(self.get_photos())

    @detail_route(methods=['post'], url_path='photos')
    def new_photo(self, request, pk=None):
        a_new_photo = Photo(user=self.request.user)
        serializer = PhotoSerializer(data=request.data,
                                     instance=new_photo)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data,
                            status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)

所以我的意图是让它ViewSet来处理这样的URL GETPOST请求:

/api/users/42/photos
Run Code Online (Sandbox Code Playgroud)

哪里GET会返回用户ID#42的照片列表,并POST会向该用户添加一张新照片.

但是,此视图只处理一种方法:POST.因为GET它返回一个错误:

{"detail":"Method \\"GET\\" not allowed."}
Run Code Online (Sandbox Code Playgroud)

如何单独处理每个HTTP方法detail_route

当我为此视图输出路由时,调试不会显示任何明显的覆盖:

Route(url=u'^{prefix}/{lookup}/photos{trailing_slash}$', mapping={'post': 'new_photo'}, name=u'{basename}-photos', initkwargs={})
Route(url=u'^{prefix}/{lookup}/photos{trailing_slash}$', mapping={'get': 'photos'}, name=u'{basename}-photos', initkwargs={}) 
Run Code Online (Sandbox Code Playgroud)

War*_*ick 5

一种选择是使用一个--decorated处理程序来处理它们GET并在处理程序内执行额外的调度:POSTdetail_route

@detail_route(methods=['get', 'post'])
def photos(self, request):
    if request.method == 'POST':
        return self.new_photo(request)

    return Response(self.get_photos())
Run Code Online (Sandbox Code Playgroud)