【发布时间】:2022-08-05 06:39:04
【问题描述】:
我正在使用 Django 整理店面环境来处理订单,并且正在努力编写我正在尝试编写的注释之一。
显着的数据模型是这样的
class Order(ClusterableModel):
\"various model fields about the status, owner, etc of the order\"
class OrderLine(Model):
order = ParentalKey(\"Order\", related_name=\"lines\")
product = ForeignKey(\"Product\")
quantity = PositiveIntegerField(default=1)
base_price = DecimalField(max_digits=10, decimal_places=2)
class OrderLineOptionValue(Model):
order_line = ForeignKey(\"OrderLine\", related_name=\"option_values\")
option = ForeignKey(\"ProductOption\")
value = TextField(blank=True, null=True)
price_adjustment = DecimalField(max_digits=10, decimal_places=2, default=0)
OrderLine 代表以特定基本价格和数量购买的一种或多种特定产品。此基本价格已从产品模型中复制,以保留创建订单时的产品价格。
因此,订单只是多个订单行的集合
复杂性来自 OrderLineOptionValue 模型,它表示基于用户做出的选择对基本价格的修改,如果产品有多个选项,则每个订单行可能有多个调整。颜色、尺寸、重量等都可能对价格产生不同的影响。
在查询 OrderLine 模型时,我已经能够使用以下查询成功地使用该行的适当行总数 (base+sum(price_adjustments))*quantity 注释每个结果:
annotation = {
\"line_total\": ExpressionWrapper((F(\"base_price\")+Coalesce(Sum(\"option_values__price_adjustment\", output_field=DecimalField(max_digits=10, decimal_places=2)), Value(0)))*F(\"quantity\"), output_field=DecimalField(max_digits=10, decimal_places=2)),
}
OrderLine.objects.all().annotate(**annotation)
对于我尝试过的所有测试,该注释似乎都能正常工作。值得注意的是,OrderLines 可能没有 price_adjustments,因此是 Coalesce。
我的问题开始于尝试用它的总和将所有它各自的行项目加在一起来注释每个订单。我最初的尝试导致了异常无法计算 Sum(\'line_total\'):\'line_total\' 是一个聚合我只能假设这确实是一个非法的 SQL 请求,因为我对 SQL 的实际知识有点生疏。
lineItemSubquery=OrderLine.objects.filter(order=OuterRef(\'pk\')).order_by()
#the same annotation as above
lineItemSubquery=lineItemSubquery.annotate(**annotation).values(\"order\")
Order.objets.all().annotate(annotated_total=Coalesce(Subquery(lineItemSubquery.annotate(sum_total=Sum(\"line_total\")).values(\'sum_total\')), 0.0))
在偶然发现this question 之后,我尝试对其进行了一些重组,虽然我能够让它返回一个数字,但它这样做不正确,似乎只返回每个订单的第一个 line_total。
lineItemSubquery=OrderLine.objects.filter(Q(order=OuterRef(\"pk\"))).annotate(**annotation).values(\"line_total\")
Order.objects.all().annotate(annotated_total=Coalesce(Subquery(lineItemSubquery), 0.0))
通过对 lineItemSubquery [1:2] 进行切片,注释也可以工作,但随后会计算出第二个行项目的数量,而忽略任何其他行项目。我认为这是所引用问题的副产品以及他们如何请求一组值的最大值(按顺序排列的第一个结果)而不是整个数据集的总和。
我的直觉说我需要找到一种方法来 Sum() 子查询,或者由于多级方面,我需要某种额外的 OuterRef 来桥接所有三个模型之间的关系?我正在认真考虑将每个 OrderLine 的计算总数直接缓存在模型字段中,以便完全避免该问题。
标签: django annotations wagtail