我已经阅读了有关序列化程序和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确定的模型返回序列化器类。
答案 0 :(得分:2)
由于您正在更新资源,因此应使用支持PUT / PATCH请求的视图,该视图正是用于通过设计(在HTTP中)更新属性。
用于只读端点,以表示单个模型实例
在特定情况下,您应该使用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,您的视图将变得尽可能通用。