django - 如何使用注释在多个表中制作反向外键

标签 django django-models

我有 3 个模型通过外键连接到一个:

class A(models.Model):
    name = models.CharField(max_length=20)

class B(models.Model):
    a = models.ForeignKey(A, on_delete=models.CASCADE)
    amount_b = models.FloatField()

class C(models.Model):
    a = models.ForeignKey(A, on_delete=models.CASCADE)
    amount_c = models.FloatField()

class D(models.Model):
    a = models.ForeignKey(A, on_delete=models.CASCADE)
    amount_d = models.FloatField()

我想使用 Django ORM 基于外键进行 JOIN 查询,以获取每个金额的总和。

在 SQL 中我会做这样的事情:

SELECT 
  a.name, 
  b_sum,
  c_sum,
  d_sum
FROM A AS a
  LEFT JOIN (SELECT b.a, sum(amount_b) as b_sum
              from B as b
              group by b.a) as AB AB.a = a.id
  LEFT JOIN (SELECT c.a, sum(amount_c) as c_sum
              from C as c
              group by a) AS AC ON AC.a = a.id
  LEFT JOIN (SELECT d.a, sum(amount_d) as d_sum
              from D as d
              group by a) AS AD ON AD.a = a.id
WHERE a.name LIKE 'init%'

但我没有在 django ORM 上找到类似的东西。

最佳答案

你可以这样做

q = A.objects.annotate(
    b_sum=Subquery(
        B.objects.filter(a=OuterRef('pk'))
                 .values('a')
                 .annotate(b_sum=Sum('amount_b'))
                 .values('b_sum')
    ),
    c_sum=Subquery(
        C.objects.filter(a=OuterRef('pk'))
                 .values('a')
                 .annotate(c_sum=Sum('amount_c'))
                 .values('c_sum')
    ),
    d_sum=Subquery(
        D.objects.filter(a=OuterRef('pk'))
                 .values('a')
                 .annotate(d_sum=Sum('amount_d'))
                 .values('d_sum')
    )
)

这看起来非常复杂的查询,也不会转换为您提到的相同 sql,但它完成了工作。

这是它生成的 sql。

SELECT "A"."id",
       "A"."name",
       (SELECT SUM(U0."amount_b") AS "b_sum" FROM "B" U0 WHERE U0."a_id" = ("A"."id") GROUP BY U0."a_id") AS "b_sum",
       (SELECT SUM(U0."amount_c") AS "c_sum" FROM "C" U0 WHERE U0."a_id" = ("A"."id") GROUP BY U0."a_id") AS "c_sum",
       (SELECT SUM(U0."amount_d") AS "d_sum" FROM "D" U0 WHERE U0."a_id" = ("A"."id") GROUP BY U0."a_id") AS "d_sum"
FROM "A"

关于django - 如何使用注释在多个表中制作反向外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60272733/

相关文章:

Django 强制使用 BigAutoField,即使默认设置为 AutoField

django - HTTP/1.0 301永久移动-Django

django - 在 Django 的 inlineformset_factory 中选择外键元素的子集

python - Django 模型继承 : ForeignKey on parent, 没有对子模型的 related_name 访问

python - 试图让 Django 在 VPS 上运行,但我一直遇到 "Invalid option to WSGI daemon process definition"

Django 日期格式问题

python - 在 Django 中使用抽象多重继承时外键冲突

python - celery - 没有名为五的模块

用于覆盖模型的 Django 设计模式

python - 字段名称选择 'reference' 不是有效选择问题