Джанго аннотировать суммой двух значений с несколькими отношениями - PullRequest
1 голос
/ 30 сентября 2019

У меня есть 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 s

Я хочуаннотировать QuerySet общим size из App (что составляет Apk.size + сумма всех Obb.size для данного AppVersion).

My App QuerySet выглядит следующим образом:

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

и подзапрос версий:

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

Этот подзапрос всегда дает самый последний AppVersion из App.

Так какой подзапрос я должен использовать для аннотирования qs с атрибутом size, рассчитанным как показано выше?

1 Ответ

1 голос
/ 30 сентября 2019

Как насчет чего-то подобного - насколько я понимаю, вы хотите получить APK приложения и размеры obb. apk и obb_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()
)
...