我如何才能正确地获得这些字段的聚合。

问题描述 投票:1回答:1

模型

class Joint(models.Model):
    welder = models.ManyToManyField(Employee, related_name='welders')
    inch_dia = models.FloatField(blank=True, null=True)

观点

context['welder'] = Joint.objects.values('welder__first_name', 'welder__last_name')
            .order_by('welder__first_name') \
            .annotate(total_inch=Sum(F('inch_dia'))/Count(F('welder__first_name'))
            , output_field=IntegerField())

给我以下错误

QuerySet.annotate() received non-expression(s): <django.db.models.fields.IntegerField>

我已经检查了另一个类似的表,如下所示,但仍然没有发生分割。

class Worker(models.Model):
    name = models.CharField(max_length=180, blank=True, null=True)

    def __str__(self):
        return str(self.name)


class WorkDone(models.Model):
    worker = models.ManyToManyField(Worker, related_name='workers')
    work_title = models.CharField(max_length=180, blank=True, null=True)
    units = models.IntegerField(blank=True, null=True)


    def __str__(self):
        return str(self.work_title)

本表的视图

  context['workers'] = Worker.objects.all() \
            .values('name', 'workers__work_title')\
            .order_by('name') \
            .annotate(total_work=
        Sum('workers__units')/Count('name')
        )
    print(context['workers'])        

打印输出

<QuerySet [{'name': 'dinesh', 'workers__work_title': 'first', 'total_work': 4}, {'name': 'ramesh', 'workers__work_title': 'first', 'total_work': 4}]>

而不是4个,应该是2个,因为总单位是4个,而工人数量是2个。

django
1个回答
1
投票

问题是 output_field 是你传递给 .annotate(..) 部分。您可以使用一个 ExpressionWrapper [Django-doc] 来解释值的类型,或者 Cast [Django-doc] 来进行转换。

from django.db.models.functions import Cast

Joint.objects.values('welder__first_name', 'welder__last_name'
).order_by('welder__first_name').annotate(total_inch=Cast(
    Sum('inch_dia')/Count('welder__first_name'),
    output_field=IntegerField()
))

也就是说,可能更有意义的是 在相反的方向进行注释。

from django.db.models.functions import Cast

Employee.objects.annotate(
    total_inch=Cast(
        Sum('welders__inch_data')/Count('welders'),
        output_field=IntegerField()
    )
)

The related_name=… 参数[Django-doc] 中指定关系的名称。反面,所以像 related_name='welders' 是不正确的,也许你想把它改名为。

class Joint(models.Model):
    welder = models.ManyToManyField(Employee, related_name='joints')
    inch_dia = models.FloatField(blank=True, null=True)

然后查询的内容是:

from django.db.models.functions import Cast

Employee.objects.annotate(
    total_inch=Cast(
        Sum('joints__inch_data')/Count('joints'),
        output_field=IntegerField()
    )
)
© www.soinside.com 2019 - 2024. All rights reserved.