Django REST Framework-使用自定义PUT方法扩展ListAPIView

时间:2018-08-08 15:06:20

标签: django-rest-framework

我使用Django REST Framework开发了用于库存管理应用程序的API。

获取产品列表的端点包括用于过滤列表的查询参数。见下文。

产品列表视图

class ProductListAPIView(ListAPIView):
    serializer_class = ProductListSerializer
    queryset = Product.objects.all()
    permission_classes = [DjangoModelPermissionsWithView]
    filter_backends = [SearchFilter, DjangoFilterBackend, OrderingFilter]
    search_fields = [
        'sku',
        'product_name',
        ...
    ]
    filter_class = ProductFilter
    pagination_class = ProductPageNumberPagination
    ordering = ['-id']
    ordering_fields = [
        'id',
        'sku',
        'product_name',
        ...
    ]

    def get_serializer_context(self, *args, **kwargs):
        return {"request": self.request}

我创建了另一个视图来处理请求,以便将产品导出到PDF,CSV等:

class ProductExportAPIView(APIView):

    def put(self, request, *args, **kwargs):
        # We use the seriaziler only to validate request.data
        serializer = ProductExportSerializer(data=request.data)
        if serializer.is_valid():
            user_id = request.user.pk
            file_key = request.data.get('file_key')
            file_name = request.data.get('file_name', '')
            extra_args = request.data.get('extra_args', {})
            product_ids = request.data.get('product_ids')
            # NOTE THAT export_file IS A CELERY TASK
            export_file.delay(user_id, file_key, file_name, product_ids, extra_args)
            return Response(status=status.HTTP_204_NO_CONTENT)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

该API可以正常工作,但仅在用户选择产品时才有效-product_ids字段用于提供要导出的产品列表。

我想通过提供ProductExportAPIView而不是提供ProductListAPIView的查询参数,让用户通过product_ids导出所有产品。 product_ids应该是一个可选字段,仅用于导出一些产品。

如何在ProductExportAPIView上启用查询参数过滤,有没有一种方法可以对它进行硬编码?我可以使用PUT方法扩展ProductListAPIView来导出产品吗?

1 个答案:

答案 0 :(得分:0)

为了使用在ProductListAPIView中定义的相同查询参数,现在ProductExportAPIView扩展了ProductListAPIView,因此它继承了我需要的所有内容:

class ProductExportAPIView(ProductListAPIView):
    permission_classes = [AllowAny]
    http_method_names = ['put'] # disable GET method inherited from ProductListAPIView

    def put(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        # We use the serializer only to validate request.data
        serializer = ProductExportSerializer(data=request.data)
        if serializer.is_valid():
            user_id = request.user.pk
            file_key = request.data.get('file_key')
            file_name = request.data.get('file_name', '')
            extra_args = request.data.get('extra_args', {})
            product_ids = request.data.get('product_ids', [])
            if len(product_ids)==0:
                product_ids = [p.pk for p in queryset]
            export_file.delay(user_id, file_key, file_name, product_ids, extra_args)
            return Response(status=status.HTTP_204_NO_CONTENT)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)