用于计算对象的 Django Model ListAPIView 序列化程序

Django Model ListAPIView serializer for counting objects

我有一个模型如下,实体:

class Entity(models.Model):
    uuid          = models.CharField(max_length=12, default=None)
    description   = models.CharField(max_length=255, default="")

我想为所有实体对象提供序列化,其中响应将提供数据库中可用的每种描述类型的计数。

例如table有以下内容:

1.cat 2.dog 3.cat 4.dog 5.bird 6.bird 7.dog

序列化将是:

狗:3 猫:2 鸟 :2

我应该如何修改以下序列化程序代码以实现此目的?

#Entity Count(per Intelligence) Search
class EntityFilterSerializer(serializers.ModelSerializer):

    class Meta:
        model = Entity
        fields = ('description')

class StandardResultsSetPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    max_page_size = 100

class EntityList(generics.ListAPIView):
    model = Entity
    serializer_class = EntityFilterSerializer
    filter_backends = [filters.SearchFilter]
    queryset = Entity.objects.order_by('id')
    search_fields = ['=uuid', ]
    pagination_class = StandardResultsSetPagination

问题更多的是获取数据而不是序列化数据。由于您的示例响应中的键不是固定的,因此创建序列化程序会有问题并且实际上不需要。您可能不需要为此视图分页。无论如何,这就是我实现它的方式:

 class EntityList(generics.ListAPIView):
    model = Entity
    filter_backends = [filters.SearchFilter]
    search_fields = ['uuid']

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        description_counts = queryset.order_by().values('description').annotate(
            count=Count('*')
        )
        return Response({
            d['description']: d['count']
            for d in description_counts
        })

如果你正在使用它,它会破坏 swagger,如果是这种情况,你将不得不提供“一些”serializer_class 来修复它。我更喜欢使用这种美感。您可以在文档字符串中编写实际响应的描述。

class EmptySerializer(serializers.Serializer):
    pass

或者,您可以决定更改响应的格式,实际上前端开发人员可能更喜欢它。

[{"description": "cat", "count": 5}, {"description": "dog", "count": 2}]

对于这种格式,你可以很容易的描述一个序列化器

class CountsSerializer(serializers.Serializer):
    description = serializers.CharField()
    count = serializers.IntegerField()

class EntityList(generics.ListAPIView):
    model = Entity
    filter_backends = [filters.SearchFilter]
    serializer_class = CountsSerializer

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        description_counts = queryset.order_by().values('description').annotate(
            count=Count('*')
        )
        serializer = self.get_serializer(description_counts, many=True)
        return Response(serializer.data)