2

我有这些模型:

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. 更复杂:我希望每个用户都能总结出所有购买物品的价格。所以购买的=真。

假设我在一个包裹中有 10 件物品,每件售价 10 美元,包裹总价应为 100 美元。假设用户购买了 5 件商品,第二笔金额应为 50 美元。

我可以很容易地用 Templetetags 做简单的查询,但我相信它可以做得更好?(希望)

4

3 回答 3

3

要汇总特定包裹的价格,a_package您可以使用此代码

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

一个关于如何进行此类查询的指南,以及描述了所有不同功能的聚合文档。

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

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

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

于 2012-08-03T08:31:36.097 回答
3

我认为最优雅的方法是在 Model 类上定义一个方法total并将其装饰为property。这将返回total(使用 Django ORM 的Sum aggregatePackageUser

类的例子Package

from django.db.models import Sum

...

class Package(models.Model):

    ...

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

在您的模板代码中,您可以将total其用作任何其他模型属性。例如:

{{ package_instance.total }}
于 2012-08-03T08:44:11.343 回答
3

@Vic Smith 得到了解决方案。

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

可能的最佳性能

您将向 Item 添加一个on_save信号,如果创建,您将更新相关package对象。

这样您可以非常快速地获得包裹价格,甚至可以进行快速排序、比较等。

另外,我并没有真正理解该purchased属性的用途。Item但是您可能希望在和之间建立多对多关系User,并将其定义UserItem为与trhough参数的连接。

无论如何,我的经验是,您通常希望在Item和对象之间建立关系,该Purchasse对象链接到User,而不是直接链接(除非您开始遇到性能问题......)。将“用户购买这个和那个Purchasse”作为事件记录使事情更容易处理。

于 2012-08-03T08:46:18.143 回答