我有这些模特:
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种功能:
在我的模板中,我想计算所有项目的每个包价格总和。 (总结我假设?)
更复杂:我希望每个用户都可以总结所购买商品的价格。所以购买=真。
假设我在一个包装中有10个物品,每个物品的价格为10美元,包裹金额应为100美元。假设用户购买5件物品,第二笔金额应为50美元。
我可以轻松地使用templetetags进行简单的查询,但我相信它可以做得更好吗? (希望)
答案 0 :(得分:3)
要计算特定包a_package
的价格,您可以使用此代码
Item.objects.filter(package=a_package).aggregate(Sum('price'))
有一个a guide on how to do these kind of queries,aggregate documentation描述了所有不同的功能。
这种查询也可以解决你的第二个问题。
UserItem.objects.filter(user=a_user).filter(purchased=True).aggregate(sum('price'))
您还可以使用annotate()
将计数附加到每个对象,请参阅上面的第一个链接。
答案 1 :(得分:3)
我认为中最优雅的方式是在Model类上定义方法total
并将其装饰为property。这将为total
或Package
返回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
属性的目的。但您可能希望在Item
和User
之间建立ManyToMany关系,并将UserItem
定义为与trhough
参数的连接。
无论如何,我的经验是,您通常希望在Item
和Purchasse
对象之间建立关系,该对象与User
相关联,而不是直接链接(除非您开始获得表演问题......)。将Purchasse
作为事件的记录“用户树枝这个和那个”使事情更容易处理。