django REST过滤器SerializerMethodField

时间:2017-09-01 08:38:34

标签: django django-rest-framework

参考官方文档。我必须按queryset进行过滤。 但我的知识有限。然后我决定使用SerializerMethodField
找到list()方法。它列出了所有项目。

问题:
我想要排除带有[]的商品

class ProductViewMissingDisplayImageSerializer(ModelControllerSerializer):
    missing_types = serializers.SerializerMethodField(read_only=True)
    def get_missing_types(self, obj: ProductView) -> typing.List[str]:
        return check_image_type(obj)

AS是输出:

{
    "product_view_pk": 78,
    "name": "ATF",
    "service": 4,
    "display_mode": "IMAGE ONLY",
    "missing_types": [
        "CONTENT IMAGE",
        "POPUP IMAGE"
    ]
},
{
    "product_view_pk": 83,
    "name": "サスティナ(化学合成油)",
    "service": 4,
    "display_mode": "IMAGE ONLY",
    "missing_types": []
},

预期结果:

    {
        "product_view_pk": 78,
        "name": "ATF",
        "service": 4,
        "display_mode": "IMAGE ONLY",
        "missing_types": [
            "CONTENT IMAGE",
            "POPUP IMAGE"
        ]
    },

以下是check_image_type

def check_image_type(obj: ProductView) -> typing.List[str]:
    # Unable to put this `dict_required_values` to `base.py` because it use class attribute
    dict_required_values = {
        settings.PREFERED_LIST[0]: [DisplayImage.CONTENT_IMAGE, DisplayImage.POPUP_IMAGE],
        settings.PREFERED_LIST[1]: [DisplayImage.HEADER_IMAGE, DisplayImage.CONTENT_IMAGE,
                                    DisplayImage.POPUP_IMAGE],
        settings.PREFERED_LIST[2]: [DisplayImage.HEADER_IMAGE, DisplayImage.POPUP_IMAGE],
        settings.PREFERED_LIST[3]: [DisplayImage.POPUP_IMAGE],
    }
    display_mode = obj.attribute.get('display_mode')
    if display_mode not in settings.PREFERED_LIST:
        return []

    required_values = dict_required_values[display_mode]
    logger.info(f'ProductView id: {obj.id}, display_mode: {display_mode}')
    logger.info(f'Required fields are {required_values}')
    qs = DisplayImage.objects.filter(attribute__product_view_pk=str(obj.id))
    for i in qs:
        try:
            logger.info(f'Removing {i.type}, {i.get_type_display()}')
            required_values.remove(i.type)
        except Exception as err:
            logger.info(f'DisplayImage id: {i.id} {err}')

    required_values = [str(DisplayImage.image_type_choices[i][1]).upper() for i in required_values]
    return required_values

我该怎么做?

更新
我的时态解决方案是用ViewSet中的列表推导替换查询集。因为我无法查询@property

class MissingDisplayImage(viewsets.ModelViewSet):
    serializer_class = ProductViewMissingDisplayImageSerializer
    queryset = ProductView.objects.all()
    permission_classes = (IsAuthenticated, ProductViewPermission)

    def list(self, request, *args, **kwargs):
        import timeit
        start_time = timeit.default_timer()
        queryset = self.filter_queryset(self.get_queryset())
        instances = [i for i in queryset if i.image_type != []] # Hack image_type here

        page = self.paginate_queryset(instances)
        if page is not None:
            serializer = self.get_serializer(instances, many=True)
            # serializer = self.get_serializer(page, many=True)
            elapsed = timeit.default_timer() - start_time
            logger.info(f'Elapsed: {elapsed}')
            return self.get_paginated_response(serializer.data)

        # serializer = self.get_serializer(queryset, many=True)
        serializer = self.get_serializer(instances, many=True)
        elapsed = timeit.default_timer() - start_time
        logger.info(f'Elapsed: {elapsed}')
        return Response(serializer.data)

1 个答案:

答案 0 :(得分:0)

据我所知,有两种方法可以实现 一种方式是写手册,如:

class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    permission_classes = (IsAuthenticated)
    serializer_class = ProductListSerializer

    def get_queryset(self):
        queryset = self.queryset
        has_missing_types = self.request.query_params.get('has_missing_types', '0')
        if has_missing_types == '1':
            product_ids = []
            for product in queryset:
                if len(product.check_image_type())>0:
                    product_ids.append(product .id)
            queryset = queryset.filter(id__in=product_ids).all()
        return queryset

/product/?has_missing_types=1

过滤

另一种方法是将missing_types保存到db并在每次更改missing_types时更新它,然后使用django-filter