【问题标题】:Django, Select related, Average, ManyToMany fieldDjango,选择相关,Average,ManyToMany 字段
【发布时间】:2016-12-11 08:11:57
【问题描述】:

假设我的模型中有客户(模型客户),并假设每个客户都有一个购物车(模型车)。每个购物车都有许多商品(模型 CartItems),然后,每个商品都与一个产品(模型 Product)有关系。

现在,我的问题来了。我想要每个客户的所有购物车的平均值,它基于每个购物车的所有项目的总和。因此,我将在下面尝试向您展示更多详细信息。

试着想象这样的关系方向: 客户->购物车->购物车项目

每个模型的简化说明:

Client (
  id #pk
)

Cart (
  id #pk
  client_id #fk that references to Client.id
)

CartItems (
  id #pk
  cart_id #fk that references to Cart.id
  product #fk that references to Product.id
)

ProductId (
  id #pk
  value # The price of the product
)

在纯 SQL 中我找到了解决方案,并且会是这样的查询:

SELECT * FROM Client
INNER JOIN Cart ON Client.id = Cart.client_id
INNER JOIN 
(SELECT AVG(c.total) AS average, cart_id FROM
    (SELECT SUM(Product.price) AS total, CartItems.cart_id AS cart_id
    FROM CartItems
    INNER JOIN Product ON CartItems.product = Product.id
    GROUP BY CartItems.cart_id) AS c GROUP BY c.cart_id) AS d
ON d.cart_id = Cart.id;

有人知道如何将此查询转换为 Django 模型的模式吗?

【问题讨论】:

  • 答案是不要打扰。只需使用原始查询。没有理由不应该这样做(除了如果您多次迭代查询集,则每次都会执行查询)
  • 但是这样做我可以正常使用分页器,就像它是一个查询集一样吗?
  • 你是对的,默认分页器不能与 rawqueryset 一起使用

标签: django django-models django-select-related


【解决方案1】:

你应该这样做:

Cart.objects.values('client_id').annotate(cant=Sum('cart_id__product__value')).aggregate(Avg('cant'))

注意注解不返回查询集,你应该返回值。

延伸阅读:Aggregations in Django

【讨论】:

  • Client.objects.select_related().order_by(order_by).annotate(total=Sum( F('cadcp__cpi__product__value') * F('cadcp__cpi__quantity'), output_field=models.DecimalField() )) .extra(select={'n_cart':'COUNT(DISTINCT cart.id)'})。使用此代码,我可以按客户检索每个购物车的总价格和购物车的数量,因此我可以进行 total/n_cart 并获得平均值,但这样我无法按平均值排序。知道如何解决这个问题吗?谢谢你的回答,对你有很大帮助。
【解决方案2】:

我的答案来得太晚了,但我在寻找类似问题的解决方案时遇到了这个问题。

在我的例子中,我在 Cart 和 CartItems 之间有一个 ManyToManyField 关系,这使它相当简单。

模型现在看起来像这样

Cart (
  id #pk
  client_id #fk that references to Client.id
  items #manytomany relationship to CartItems
)

CartItems (
  id #pk
  product #fk that references to Product.id
)

要获得每个购物车的平均值,查询应该如下所示

Cart.objects.annotate(carts_avg=Avg('items__product__value'))

【讨论】:

    猜你喜欢
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    相关资源
    最近更新 更多