Django:嵌套查询多对多关系的聚合函数

时间:2021-07-27 11:51:17

标签: django django-models django-rest-framework django-views django-forms

我的model.py是

class Place(models.Model):
    id = models.IntegerField(primary_key=True)
    location = models.CharField(max_length=100)

    class Meta:
        db_table = 'place'
        managed=False
        
        
class Session(models.Model):
    id = models.IntegerField(primary_key=True)
    place = models.ForeignKey(Place,related_name='session',on_delete=models.CASCADE, null=True)
    start = models.DateField(auto_now=True)
    counts = models.IntegerField()

    class Meta:
        db_table = 'session'
        managed=False


class Animal(models.Model):
    id = models.IntegerField(primary_key=True)
    sess = models.ForeignKey(Session,related_name='details',on_delete=models.CASCADE, null=True)
    type = models.CharField(max_length=100)
    is_active = models.BooleanField()
    length = models.DecimalField(max_digits=6, decimal_places=2)


    class Meta:
        db_table = 'animal'
        managed=False

我需要根据特定日、周、月或年的选择获得一个汇总表,其中包含特定位置的最小、最大、标准偏差、平均值和动物数量。我尝试使用聚合和注释,但结果并不如预期。请向我建议如何实现?

Serilaizer.py

class AnimalSerializers(FlexFieldsModelSerializer):
    class Meta:
        model = Animal
        fields = ["is_active","type"]


class SessionSerializers(FlexFieldsModelSerializer):
    class Meta:
        model = Session
        fields = ["start","count"]
        expandable_fields = {
          'details': (AnimalSerializers, {'many': True})
        }

class PlaceSerializers(FlexFieldsModelSerializer):
    # countsessiontotank = serializers.PrimaryKeyRelatedField(read_only=True)
    length_max = serializers.DecimalField(max_digits=10, decimal_places=2)
    length_min = serializers.DecimalField(max_digits=10, decimal_places=2)
    length_avg = serializers.DecimalField(max_digits=10, decimal_places=2)
    length_std = serializers.DecimalField(max_digits=10, decimal_places=2)
    active_percent = serializers.IntegerField()
    total_counts = serializers.IntegerField()
    class Meta:
        model = Place
        fields = ["location","length_max","length_min","length_avg","length_std","total_counts","active_percent"]
        expandable_fields = {
            'session': (SessionSerializers, {'many': True})
        }

视图.py

class PlaceModelViewSets(ModelViewSet):
    queryset = Place.objects.values('location')
    serializer_class = PlaceSerializer

    def get_queryset(self):
        queryset = Place.objects.values('location').annotate(total_count=Count('session__details__is_active'), def_count = Count('session__details__is_active',filter=Q(session__details__is_active=True)))
        queryset = queryset.annotate(def_percent = ExpressionWrapper(F('def_count')/F('total_count'), output_field=FloatField())) //For percentage of active counts out of total counts
        queryset = queryset.annotate(            
            total_counts = Count('session__details__is_active'),
            length_max=Max('session__details__length'),
            length_min=Min('session__details__length'),
            length_avg=Avg('session__details__length'),
            length_std=StdDev('session__details__length')
        )
        return queryset

我想得到的输出是

[
    {
        "location": "Loc 1",
        "length_max": "38.74",
        "length_min": "38.74",
        "length_avg": "38.74",
        "length_std": "2.37",
        "total_counts": 4,
        "active_percent": 50,
        "session": [
            {
                "start": "2021-01-01",
                "count": 900,
                "details": [
                    {
                        "type": "dog"
                    }
                ]
            },
        ]   
    },
    {
        "location": "Loc 1",
        "length_max": "43.47",
        "length_min": "38.74",
        "length_avg": "41.10",
        "length_std": "2.37",
        "total_counts": 4,
        "active_percent": 50,
        "session": [
            {
                "start": "2021-01-02",
                "count": 400,
                "details": [
                    {
                        "type": "dog"
                    }
                ]
            },
        ]   
    },
    {
        "location": "Loc 4",
        "length_max": "28.47",
        "length_min": "28.47",
        "length_avg": "28.47",
        "length_std": "5.60",
        "total_counts": 4,
        "active_percent" : 50,
        "session": [
            {
                "start": "2021-01-02",
                "count": 800,
                "details": [
                    {
                        "type": "cat"
                    },
                ]
            }
        ]
    },
    {
        "location": "Loc 4",
        "length_max": "22.45",
        "length_min": "22.45",
        "length_avg": "22.45",
        "length_std": "5.60",
        "total_counts": 4,
        "active_percent" : 50,
        "session": [
            {
                "start": "2021-01-03",
                "count": 750,
                "details": [
                    {
                        "type": "cat"
                    },
                ]
            }
        ]
    }
]

但是我得到的输出是

[
    {
        "location": "Loc 1",
        "length_max": "43.47",
        "length_min": "38.74",
        "length_avg": "41.10",
        "length_std": "2.37",
        "total_counts": 8,
        "session": [
            {
                "start": "2021-01-01",
                "count": 600,
                "details": [
                    {
                        "is_active": true,
                        "type": "dog"
                    },
                    {
                        "is_active": false,
                        "type": "dog"
                    },
                    {
                        "is_active": true,
                        "type": "dog"
                    },
                    {
                        "is_active": false,
                        "type": "dog"
                    }
                ]
            },
            {
                "start": "2021-01-02",
                "count": 400,
                "details": [
                    {
                        "is_active": false,
                        "type": "dog"
                    },
                    {
                        "is_active": true,
                        "type": "dog"
                    },
                    {
                        "is_active": false,
                        "type": "dog"
                    },
                    {
                        "is_active": true,
                        "type": "dog"
                    }
                ]
            },
            {
                "start": "2021-01-01",
                "count": 300,
                "details": []
            }
        ]
    },
    {
        "location": "Loc 4",
        "length_max": "34.85",
        "length_min": "20.56",
        "length_avg": "26.58",
        "length_std": "5.60",
        "total_counts": 8,
        "session": [
            {
                "start": "2021-01-02",
                "count": 800,
                "details": [
                    {
                        "is_active": false,
                        "type": "cat"
                    },
                    {
                        "is_active": true,
                        "type": "cat"
                    },
                    {
                        "is_active": false,
                        "type": "cat"
                    },
                    {
                        "is_active": true,
                        "type": "cat"
                    }
                ]
            },
            {
                "start": "2021-01-03",
                "count": 750,
                "details": [
                    {
                        "is_active": true,
                        "type": "cat"
                    },
                    {
                        "is_active": false,
                        "type": "cat"
                    },
                    {
                        "is_active": true,
                        "type": "cat"
                    },
                    {
                        "is_active": false,
                        "type": "cat"
                    }
                ]
            }
        ]
    }
]

有额外的字段。当我尝试计算“active_percent”时,我得到的只是“active_percent”字段不存在。

0 个答案:

没有答案