如何在Django REST中实现方法?

时间:2018-01-30 11:05:34

标签: python django django-rest-framework

有下一个Django REST问题。

我有看法。

class MessageViewSet(viewsets.ModelViewSet):
    serializer_class = MessageSerializer
    queryset = Message.objects.filter(isread = False)
    def mark_read():
        queryset = Message.objects.update(isread=True)
        return Response({'read':queryset})

和urls.py中的路由器

router = SimpleRouter() router.register(r'api/get_messages', MessageViewSet)

urlpatterns = [
    url(r'^$', MainView.as_view(), name='main'),
    url(r'^', include(router.urls)) ]

现在我有'get_messages'页面显示所有列表。

当我访问'mark_read'页面时,如何实现一个方法,将模型实例的'isread'值从False更改为True? 如您所见,我试图在课堂上编写方法。但是,当我试图用这种方式在网址中调用它时:

router.register(r'api/mark_read', MessageViewSet.mark_read),

出现错误。

  

断言queryset不是None,'base_name参数未指定,并且可能'\'   AssertionError:base_name参数未指定,并且无法自动确定视图集中的名称,因为它没有.queryset属性。

也许我不应该使用路由器,并以其他方式重写视图和网址。如果你知道如何解决这个问题,请回答。谢谢。

3 个答案:

答案 0 :(得分:2)

您可以使用detail_routelist_route装饰器。

from rest_framework.decorators import list_route

class MessageViewSet(viewsets.ModelViewSet):

    @list_route()
    def mark_read(self, request):
        queryset = Message.objects.update(isread=True)
        return Response({'read':queryset})

mark_read可以使用api/get_messages/mark_read方法。而且您不需要创建单独的路由器,只需使用您为MessageViewSet

创建的路由器

docs reference

答案 1 :(得分:2)

由于您使用的是模型视图集,因此您可以直接使用put或patch rest方法将所需字段作为数据发送到所需字段。 理想情况下,休息时不应更改模型值。如果你真的想要一个不同的终点,那就把list_route或detail_route装饰器放在你的mark_read方法上,并使它们成为一个只有put和/或patch调用的有效调用

from rest_framework.decorators import list_route

    class MessageViewSet(viewsets.ModelViewSet):

        @list_route(methods=['Patch', 'PUT'])
        def mark_read(self, request):
            queryset = Message.objects.update(isread=True)
            return Response({'read':queryset})

答案 2 :(得分:0)

感谢@ ivan-semochkin和@Shaumux的回复。建议真有帮助。

这是我的路线。我使用了detail_route而不是list_route。

@detail_route(methods=['get','put'], url_name='mark_read/')
def mark_read(self, request, pk=None):
    queryset = Message.objects.filter(pk=pk).update(isread=True)
    return Response({'read':queryset})

现在,'isread'值正在改变,我访问'mark_read'页面。 链接:“api / get_messages / pk / mark_read”

有谁知道,是否可以通过下一个方式建立链接: “api / get_messages” - 列表,“api / mark_read / pk” - 更改读取值。

是否可以创建这样的东西? “API / mark_read?= PK”