Django Aggregate有几个型号

时间:2012-08-03 08:14:21

标签: django

我有这些模特:

class Package(models.Model):
    title = CharField(...)

class Item(models.Model)
    package = ForeignKey(Package)
    price = FloatField(...)

class UserItem(models.Model)
    user = ForeignKey(User)
    item = ForeignKey(Item)
    purchased = BooleanField()

我正在尝试以最佳性能实现2种功能:

  1. 在我的模板中,我想计算所有项目的每个包价格总和。 (总结我假设?)

  2. 更复杂:我希望每个用户都可以总结所购买商品的价格。所以购买=真。

  3. 假设我在一个包装中有10个物品,每个物品的价格为10美元,包裹金额应为100美元。假设用户购买5件物品,第二笔金额应为50美元。

    我可以轻松地使用templetetags进行简单的查询,但我相信它可以做得更好吗? (希望)

3 个答案:

答案 0 :(得分:3)

要计算特定包a_package的价格,您可以使用此代码

Item.objects.filter(package=a_package).aggregate(Sum('price'))

有一个a guide on how to do these kind of queriesaggregate documentation描述了所有不同的功能。

这种查询也可以解决你的第二个问题。

UserItem.objects.filter(user=a_user).filter(purchased=True).aggregate(sum('price'))

您还可以使用annotate()将计数附加到每个对象,请参阅上面的第一个链接。

答案 1 :(得分:3)

我认为中最优雅的方式是在Model类上定义方法total并将其装饰为property。这将为totalPackage返回User(使用Django ORM的Sum aggregate)。

班级Package的示例:

from django.db.models import Sum

...

class Package(models.Model):

    ...

    @property
    def total(self):
        return self.item_set.aggregate(Sum('price'))

在模板代码中,您可以使用total作为任何其他模型属性。 E.g:

{{ package_instance.total }}

答案 2 :(得分:3)

@Vic Smith得到了解决方案。

但如果您愿意,我会在price模型上添加package属性

  

可能的最佳表现

您可以向Item添加on_save信号,如果已创建,则更新相关的package对象。

通过这种方式,您可以非常快速地获得包价,甚至可以快速排序,比较等等。

另外,我并没有真正达到purchased属性的目的。但您可能希望在ItemUser之间建立ManyToMany关系,并将UserItem定义为与trhough参数的连接。

无论如何,我的经验是,您通常希望在ItemPurchasse对象之间建立关系,该对象与User相关联,而不是直接链接(除非您开始获得表演问题......)。将Purchasse作为事件的记录“用户树枝这个和那个”使事情更容易处理。