django - Django admin annotation - Sum 相关模型的字段
问题描述
我有一个 django-admin 仪表板/列表,它尝试使用我认为无法正常工作的带注释的查询集来跟踪和总结“工作”。作为表格的一部分,我显示了来自相关对象的数据量的计算字段(由带注释的查询集提供)。
实际上,它是跟踪计算机设备及其各自存储设备的工作的作业列表,因此作业可以有多个设备,这些设备可以有多个存储设备。设备和存储都可以包含数据量(就像手机可以具有内部存储器和可移动存储卡一样。)对于某些工作,设备可能是裸硬盘驱动器或具有 5 个 HDD 的 PC 塔,所以我试图容纳这些场景...
模型.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)
...
对于 Job 的管理模型,我尝试了以下方法,这似乎可行,但是当我过滤(例如基于对作业名称的文本搜索)时,数据量的总数会猛增
管理员.py
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
我注意到,如果我搜索/过滤一个职位名称并获得多次点击,它似乎将数据总和乘以结果数,但如果我过滤其他字段(使用 list_filter 字段)它不会发生.
谁能看到我哪里出错了?我很感激任何建议。
韩
解决方案
尽量不要将多个聚合与annotate()结合起来,因为这会产生错误的结果(因为使用连接而不是子查询)
那么该怎么做呢?使用子查询,类似的东西应该可以完成这项工作:
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
您可以尝试再做一个注释以获得 and 的总和_device_capacity
,_storage_capacity
但我想在 python 中对其求和很容易,所以也许不需要打扰数据库。
推荐阅读
- ios - 如何从 TabBarController 打开特定的 ViewController
- php - 为单个页面禁用 nginx 缓存会给出 404
- java - Java Robot 不能输入这个句子。为什么?
- javascript - 使用 css 位置更改元素的位置:绝对
- c - 从 c 文件写入 h 文件,然后在 C 中写入另一个 h 文件
- python - 如何删除“!” 除了最后一个句子?
- python - 如何将循环的值传递给函数?
- python - 将 noughts and crosss 游戏转换为 4 x 4 网格
- android - java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“java.lang.String okhttp3.ResponseBody.string()”
- python - 4阶张量对称部分的Sympy计算