序列化程序是否具有等效的get_model?

时间:2019-07-11 04:48:02

标签: django serialization django-rest-framework

我已经阅读了有关序列化程序和Googled的文档(很多),但是没有找到我想要的确切答案。

我正在尝试编写一个通用的“存档”过程(类),以处理根据URL中传递的内容将任何模型实例的状态字段更改为“已存档”的情况。

例如:

example.com/archive/clients.client/123

这会将客户端模型的ID 123的状态更改为“已存档”。

这是我的URLconf:

path('archive/<model>/<int:pk>/', Archive.as_view()),

这是我的视图类。我首先要针对特定​​的模型进行此工作,所以我已经复制了该代码,并试图将其改编为更通用的代码。另外,我知道这需要更多的防弹功能,但是我试图显示我的代码的最简单版本。

class Archive(RetrieveAPIView):

    def retrieve(self, request, model=None, pk=None, *args, **kwargs):
        app, model_name = model.split('.')

        get_model = apps.get_model
        model = get_model(app, model_name)
        self.queryset = model.objects.all()

        instance = self.get_object(pk=pk)

        if instance.status == 'archived':
            return APIMessage('That item has already been archived.', message_code='already_archived')

        setattr(instance, 'status', 'archived')
        instance.save()

        serializer = self.get_serializer(instance)
        return Response(serializer.data)

当我尝试按原样运行时,我得到:

'Archive' should either include a `serializer_class` attribute, or override the `get_serializer_class()` method.

这几乎是我所期望的,但实际上我一无所有我可以将serializer_class设置为的东西,如果将其设置为None,则会遇到相同的错误。当然,我已经对get_serializer_class有所了解,但这就是我需要get_model之类的地方,除了它会根据我从URL确定的模型返回序列化器类。

1 个答案:

答案 0 :(得分:2)

由于您正在更新资源,因此应使用支持PUT / PATCH请求的视图,该视图正是用于通过设计(在HTTP中)更新属性。

RetrieveAPIView是:

  

用于只读端点,以表示单个模型实例

在特定情况下,您应该使用DRF中最通用的APIView,因为它不需要定义serializer_class和其他您不会使用的属性。

from rest_framework.views import APIView


class Archive(APIView):
    def put(self, request, model=None, pk=None, *args, **kwargs):
        app, model_name = model.split('.')

        get_model = apps.get_model
        model = get_model(app, model_name)
        self.queryset = model.objects.all()

        instance = self.get_object(pk=pk)

        if instance.status == 'archived':
            return APIMessage('That item has already been archived.', message_code='already_archived')

        setattr(instance, 'status', 'archived')
        instance.save()

        return Response({'success': True})

    def patch(self, request, *args, **kwargs):
        return self.put(request, *args, **kwargs)

这应该可以完成工作。我还映射了PATCH方法以执行PUT逻辑,这意味着您可以使用这两种HTTP方法来更新模型实例。

现在,借助APIView,您的视图将变得尽可能通用。