django - 序列化程序是否有 get_model 等效项?
问题描述
我已经阅读了有关序列化程序和谷歌搜索的文档(很多),但还没有找到我正在寻找的确切答案。
我正在尝试编写一个通用的“归档”过程(类)来处理根据 URL 中传递的内容将任何模型实例的状态字段更改为“归档”。
例如:
example.com/archive/clients.client/123
这会将 Client 模型的 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 确定的模型返回序列化程序类。
解决方案
由于您正在更新资源,因此您应该使用支持 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 的帮助下尽可能通用。