来自 3 层嵌套的 Django ORM 总和价格

Posted

技术标签:

【中文标题】来自 3 层嵌套的 Django ORM 总和价格【英文标题】:Django ORM sum prices from 3 level nested 【发布时间】:2020-01-19 10:05:10 【问题描述】:

我有这些模型和经理:


class ItemManager(models.Manager):
    use_for_related_fields = True

    def get_queryset(self):
        qs = super().get_queryset()
        return qs.annotate(total_price=ExpressionWrapper(
            F('gross_price') * F('qty'), output_field=models.DecimalField())
        )


class OrderManager(models.Manager):
    use_for_related_fields = True

    def get_queryset(self):
        qs = super().get_queryset()
        return qs.annotate(total_price=Sum(items__total_price))  # this doesnt work



class Order(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length='50')


class Item(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    price = models.DecimalField(max_digits=14, decimal_places=2)
    qty = models.IntegerField()
    order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE)

    objects = ItemManager()

我想得到订单的总价,像这样:

for sale in Order.objects.all():
    print(sale.total_price)

错误:

django.core.exceptions.FieldError: Unsupported lookup 'total_price' for UUIDField or join on the field not permitted.

我可以为每个项目获取total_price,我想使用该total_price 来获取所有项目的总和。 我需要这种方式,因为我将在具有多个订单作为子元素的模型中使用该销售总价。

【问题讨论】:

【参考方案1】:

如果您查询相关模型,这些相关模型不会“通过”.objects 管理器。您可以覆盖 ._base_manager 等。但我强烈建议不要这样做。

您可能最好在OrderManager 本身中完成工作:

class OrderManager(models.Manager):
    use_for_related_fields = True

    def get_queryset(self):
        return super().get_queryset().annotate(
            total_price=Sum(F('items__price') * F('items__qty'))
        )

【讨论】:

我知道这个解决方案,但我需要这种方式,因为我将使用它来获取订阅中所有订单的总和,并且订阅有多个订单。所以我真的需要这种方式。 @MirzaDelic:作为帮助,您可以覆盖Items_base_manager 经理。但我个人认为它反对“Python 之禅”。显式优于隐式是规则 #2 :)

以上是关于来自 3 层嵌套的 Django ORM 总和价格的主要内容,如果未能解决你的问题,请参考以下文章

Django模型层—ORM

django orm 和 postgresql 的累积(运行)总和

Django之ORM

Django模型和ORM

Django:将价格注释到行,然后按字段对行进行分组,并将价格总和注释到组

使用 Django ORM 注释查询以计算 2 个表值的总和