当我尝试在视图集上使用 Django Rest Framework 额外操作时,我无法使装饰器的
serializer_class
工作。
class ClientViewSet(ModelViewSet):
queryset = Client.objects.all()
serializer_class = ClientSerializer
def get_queryset(self):
# Do things
def get_serializer_class(self):
if self.action in ["create"]:
return CreateClientSerializer
elif self.action in ["retrieve"]:
return ClientDetailSerializer
return self.serializer_class
@action(detail=True, methods=["get"], serializer_class=ClientDetailSerializer)
def get_by_name(self, request, name=None):
"""
Get one Client searching by name.
@param request:
@param name: Client code
@return: Response
"""
queryset = get_object_or_404(Client, name__iexact=name)
serializer = self.get_serializer(queryset)
return Response(serializer.data)
因此,即使额外的操作据称会覆盖 ViewSet 默认序列化器类,我仍然得到
ClientSerializer
而不是 ClientDetailSerializer
。
官方文档指出...
装饰器允许您覆盖任何视图集级别的配置,例如
、permission_classes
、serializer_class
...:filter_backends
我的
get_serializer_class
覆盖默认为 ViewSet serializer_class
属性,用于我的额外操作。如果我理解正确的话,这基本上就是 GenericAPIView
get_serializer_class
在幕后所做的事情:
def get_serializer_class(self):
"""
(...)
"""
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
)
return self.serializer_class
我想我在这里遗漏了一些明显的东西。只是不明白什么...
如有任何帮助,我们将不胜感激。预先感谢:)
当您重写
get_serializer_class
而不调用此类的超级时,超级类不会运行。
用户此:
def get_serializer_class(self):
if self.action in ["create"]:
return CreateClientSerializer
elif self.action in ["retrieve"]:
return ClientDetailSerializer
return super().get_serializer_class()
为什么不这样使用呢?我猜你在 get_serializer_class 中做错了什么。
@action(detail=True, methods=["get"], serializer_class=ClientDetailSerializer)
def get_by_name(self, request, name=None):
"""
Get one Client searching by name.
@param request:
@param name: Client code
@return: Response
"""
object = get_object_or_404(Client, name__iexact=name)
serializer = ClientDetailSerializer(object)
return Response(serializer.data)
get_serializer_class
则优先,因此操作中的 serializer_class=ClientDetailSerializer
没有意义。
基本上
@action
装饰器创建一个新动作,就像 - list
、retrieve
、etc
。
所以在这里你可以在
get_serializer_class
本身添加额外的条件返回,例如:
def get_serializer_class(self):
if self.action in ["create"]:
return CreateClientSerializer
if self.action in ["retrieve"]:
return ClientDetailSerializer
# here self.action will be the name of the function name
if self.action == "get_by_name":
return ClientDetailSerializer
return self.serializer_class
我知道在这里发帖已经太晚了,但可能会对像我这样的人有所帮助。