通过SerializerMethodField

时间:2018-03-09 23:12:13

标签: django django-rest-framework django-queryset

如何根据Serializer中的计算字段过滤结果?我试着像任何其他领域一样对待它,但是django不喜欢它。

串行化

class ImageSerializer(serializers.ModelSerializer):
    is_annotated = serializers.SerializerMethodField('has_annotation')

    class Meta:
        model = Image
        fields = '__all__'

    @staticmethod
    def has_annotation(image):
        return image.annotation_set.count() > 0

class ImageViewSet(viewsets.ModelViewSet):
    serializer_class = ImageSerializer
    lookup_field = 'id'
    permission_classes = [
        Or(IsAdmin),
        IsAuthenticated
    ]

    def get_queryset(self):
        queryset = Image.objects

        is_annotated_filter = self.request.query_params.get('is_annotated', None)
        if is_annotated_filter is not None:
            queryset = queryset.filter.annotate(
                cnt=Count('annotation')).filter(cnt__gte=1)

        queryset_order = get_queryset_order(self.request)
        return queryset.order_by(queryset_order).all()

1 个答案:

答案 0 :(得分:1)

我认为您误解了:1)序列化程序MethodField主要用途是READ-ONLY,并且序列化程序不会用于过滤查询集。

我会更像这样过滤它:

from django.db.models import Count

queryset.filter.annotate(
    cnt=Count('annotation_set')
).filter(cnt__gte=1)

但是......你可以做得更好:

1)只需在ViewSet中注释您的查询集

from django.db.models import Count
queryset = Image.objects.annotate(
    cnt_annotations=Count('annotation_set')
)

2)然后在序列化器中执行以下操作:

@staticmethod
def has_annotation(image):
    if hasattr(obj, 'has_annotation'):
        return bool(obj.cnt_annotations)
    else:
        return None