Django 具有多个序列化程序的视图集上的DRF选项请求

Django 具有多个序列化程序的视图集上的DRF选项请求,django,django-rest-framework,Django,Django Rest Framework,我在我的视图集上使用了一个mixin,这样多个序列化程序可以跨不同的和任意的视图使用 我有一个名为invoice的额外操作,它只是一个普通的更新,但使用了不同的序列化程序。我需要在端点执行选项请求,以获取元素的选项。问题是,当我执行请求时,它从默认更新中提取序列化程序-ordersializer,而不是InvoiceSerializer。如何从正确的序列化程序中选择选项 class MultipleSerializerMixin: """ Mixin that allows fo

我在我的视图集上使用了一个mixin,这样多个序列化程序可以跨不同的和任意的视图使用

我有一个名为
invoice
的额外操作,它只是一个普通的更新,但使用了不同的序列化程序。我需要在端点执行选项请求,以获取
元素的选项。问题是,当我执行请求时,它从默认更新中提取序列化程序-
ordersializer
,而不是
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)
更新:


因此,在检查后,似乎在执行选项请求时,
view.action
metadata
而不是
invoice
,这解释了为什么序列化程序默认为
view.serializer\u class

一种解决方法是创建一个可通过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)
如果您有使用不同序列化程序的多个操作,则更简单的解决方案是覆盖视图的
选项
方法,并从查询参数设置操作。这可以添加到
MultipleSerializerMixin
中,使其成为使用此mixin的所有视图的默认行为

def options(self, request, *args, **kwargs):
    self.action = request.query_params.get('action')
    return super().options(request, *args, **kwargs)

Override
get\u serializer\u class
方法已足够,OPTIONS请求将检测要使用的序列化程序:

def get_serializer_class(self):
   if self.request.method == 'GET':
      return ReadOnlyShopSerializer
   return ShopSerializer