Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django管理注释-相关模型的总和字段_Django_Django Admin - Fatal编程技术网

Django管理注释-相关模型的总和字段

Django管理注释-相关模型的总和字段,django,django-admin,Django,Django Admin,我有一个django管理仪表板/列表,它试图跟踪和总结带有注释的queryset的“作业”,我认为它工作不正常。作为表的一部分,我显示了来自相关对象的数据量的计算字段(由带注释的queryset提供) 实际上,它是一个作业列表,跟踪针对计算机设备及其各自存储设备的工作,因此一个作业可以有多个设备,这些设备可以有多个存储设备。设备和存储器都可以包含数据量(就像手机可以拥有内置内存和可移动存储卡一样)。在某些作业中,设备可能是裸硬盘或带有5个HDD的PC塔,因此我正在尝试适应这些场景 models.

我有一个django管理仪表板/列表,它试图跟踪和总结带有注释的queryset的“作业”,我认为它工作不正常。作为表的一部分,我显示了来自相关对象的数据量的计算字段(由带注释的queryset提供)

实际上,它是一个作业列表,跟踪针对计算机设备及其各自存储设备的工作,因此一个作业可以有多个设备,这些设备可以有多个存储设备。设备和存储器都可以包含数据量(就像手机可以拥有内置内存和可移动存储卡一样)。在某些作业中,设备可能是裸硬盘或带有5个HDD的PC塔,因此我正在尝试适应这些场景

models.py:

class Job(models.Model):
    ...
    job_number = models.CharField(max_length=50)
    job_name = models.CharField(max_length=100)
    ...

class Device(models.Model):
    ...
    device_number = models.CharField(max_length=50)
    job = models.ForeignKey(Job, null=True, on_delete=models.CASCADE)
    capacity = models.FloatField(null=True)
    ...

class Storage(models.Model):
    ...
    storage_number = models.CharField(max_length=50)
    device = models.ForeignKey(Device, null=True, on_delete=models.CASCADE)
    capacity = models.FloatField(null=True)
    ...
对于作业的管理模型,我尝试了以下方法,这似乎是可行的,但是当我过滤(例如,基于对作业名称的文本搜索)时,数据量的总数会激增

管理员

class JobAdmin(admin.ModelAdmin)

    def get_queryset(self, request):
        queryset = super().get_queryset(request)
        queryset = queryset.annotate(
            _device_count=Count("device", distinct=True),
            _device_volume=Sum("device__capacity", distinct=True)+Sum("device__storage__capacity", distinct=True)
           )
        return queryset

    def data_label(self,obj):
        return obj._device_volume
我注意到,如果我搜索/筛选一个作业名称并获得多个点击,它似乎会将数据总和乘以结果数,但如果我筛选其他字段(使用列表过滤器字段),则不会出现这种情况

谁能看出我错在哪里?谢谢你的建议


Han

尽量不要将多个聚合与注释()结合起来,因为(因为使用连接而不是子查询

那么怎么做呢?使用时,应使用以下方法:

from django.db.models import OuterRef, Subquery, Sum, Count


def get_queryset(self, request):
    queryset = super().get_queryset(request)
    queryset = queryset.annotate(
        _device_count=Subquery(
            Device.objects.filter(job=OuterRef("pk"))
            .values("job")
            .annotate(cnt=Count("id"))
            .values("cnt")
        ),
        _device_capacity=Subquery(
            Device.objects.filter(job=OuterRef("pk"))
            .values("job")
            .annotate(vol=Sum("capacity"))
            .values("vol")
        ),
        _storage_capacity=Subquery(
            Storage.objects.filter(device__job=OuterRef("pk"))
            .values("device__job")
            .annotate(vol=Sum("capacity"))
            .values("vol")
        ),
    )
    return queryset

您可以尝试再做一次注释,以获得
\u设备\u容量
\u存储\u容量
的总和,但我想在python中求和是很容易的,所以可能不需要麻烦数据库。

哇,谢谢,伙计。通过一个具体的、相关的例子来展示这些概念是非常有用的。我是django nuffy,所以我想我会从这些文件中学到很多东西。顺便说一句,它工作完美!我可以看到如何在查询集之外将它们作为函数的一部分求和,但出于兴趣,我应该如何在查询集中组合它们?它应该是这样的:
.annotate(\u total\u capacity=F('u device\u capacity')+F('u storage\u capacity'))
,但您可能还需要将其包装在一个