【问题标题】:Django annotate by sum of two values with multiple relationsDjango通过具有多个关系的两个值的总和进行注释
【发布时间】:2020-01-30 00:20:43
【问题描述】:

我有 4 个模型:

class App(models.Model):
   ...

class AppVersion(models.Model):
   app = models.ForeignKey(App)
   version_code = models.IntegerField()

   class Meta:
        ordering = ('-version_code',)
   ...

class Apk(models.Model):
   version = models.OneToOneField(AppVersion)
   size = models.IntegerField()

class Obb(models.Model):
   version = models.ForeignKey(AppVersion)
   size = models.IntegerField()

AppVersion 版本总是有一个Apk,但可能有0、1 或2 个Obb

我想用App 的总size 来注释QuerySet(这是Apk.size + 所有Obb.size 的总和对于给定的AppVersion)。

我的App QuerySet 看起来像这样:

qs = App.objects.filter(is_visible=True)

版本子查询是:

latest_versions = Subquery(AppVersion.objects.filter(application=OuterRef(OuterRef('pk'))).values('pk')[:1])

这个子查询总是给出App 中最新的AppVersion

那么我应该使用什么子查询来注释qssize 属性计算如上所示?

【问题讨论】:

    标签: django django-annotate django-subquery


    【解决方案1】:

    这样的事情怎么样 - 据我了解,您需要一个 Apps apk,并且 obb 大小相加。 apkobb_set 可以替换为字段相关名称,如果您添加了一个。我选择的应该是 django OneToOne 和 Fk 相关名称的默认值。

    from django.db.models import F, Value, Sum, IntegerField
    
    qs = App.objects.filter(
        is_visible=True
    ).annotate( 
        apk_size=Sum('apk__size'), 
        obb_size=Sum('obb_set__size')
    ).annotate( 
        total_size=Value( 
        F('apk_size') + F('obb_size'), 
        output_field=IntegerField()
    )
    

    【讨论】:

    • 一个App 有多个AppVersion,我只需要size 用于给定查询集中的第一个AppVersion,但您建议的代码将输出ApkObbs 适用于所有版本。
    • 这个模型是什么样子的? AndroidApplicationVersion
    • 抱歉,我已经编辑了问题——它是AppVersion
    • 哪个字段决定哪个版本是最新的?
    • 再次更新了有问题的代码。最新版本是最大的version_code(查询集按字段version_code倒序排列,所以它是查询集中的第一项)。
    猜你喜欢
    • 2016-06-17
    • 2021-05-26
    • 1970-01-01
    • 2018-10-05
    • 2021-06-24
    • 2018-09-15
    • 2021-10-22
    • 2011-05-05
    • 2012-03-20
    相关资源
    最近更新 更多