我在 View 集上使用 mixin,以便可以在不同的 viewset actions 上使用多个序列化器和任何custom actions .
我有一个名为 invoice
的额外操作这只是一个正常的更新,但使用了不同的序列化器。我需要在端点执行 OPTIONS 请求以获取 <select>
的选项元素。问题是,当我执行请求时,它从默认更新中获取序列化器 - OrderSerializer
而不是InvoiceSerializer
。如何从正确的序列化器中获取选项?
class MultipleSerializerMixin:
"""
Mixin that allows for multiple serializers based on the view's
`serializer_action_classes` attribute.
ex.
serializer_action_classes = {
'list': ReadOnlyListSerializer,
'retrieve': ReadOnlyDetailSerializer,
}
"""
def get_serializer_class(self):
try:
return self.serializer_action_classes[self.action]
except (KeyError, AttributeError):
return super().get_serializer_class()
class OrderAPIViewSet(MultipleSerializerMixin,
viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = serializers.OrderSerializer
serializer_action_classes = {
'invoice': serializers.InvoiceSerializer,
}
@action(detail=True, methods=['put'], url_name='invoice')
def invoice(self, request, *args, **kwargs):
"""
Invoice the order and order lines.
"""
return self.update(request, *args, **kwargs)
更新:
检查 determine_actions
method in metadata.SimpleMetadata
后似乎在执行 OPTIONS 请求 view.action
时是 metadata
而不是invoice
这解释了为什么序列化器默认为 view.serializer_class
。
最佳答案
一种解决方法是创建一个 extra action as a schema endpoint可以通过手动将操作设置为发票
的 GET 请求来访问。
@action(detail=True, methods=['get', 'put'])
def invoice_schema(self, request, *args, **kwargs):
self.action = 'invoice'
data = self.metadata_class().determine_metadata(request, self)
return Response(data, status=status.HTTP_200_OK)
如果您有多个使用不同序列化器的操作,则更干燥的解决方案是覆盖 View 的 options
方法并从查询参数设置操作。可以将其添加到 MultipleSerializerMixin
中,使其成为使用此 mixin 的所有 View 的默认行为。
def options(self, request, *args, **kwargs):
self.action = request.query_params.get('action')
return super().options(request, *args, **kwargs)
关于django - 具有多个序列化器的 View 集上的 DRF 选项请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60074411/