我遇到了一些性能问题,因为我正在进行大量的查询调用,而我不确定如何减少。
user_item_rel_set是用户与项目之间的m2m关系,表示用户为特定项目支付了多少费用。每个项目可以有多个用户和买家,我正在尝试获取特定用户的m2m关系。
# find anything that you bought or used and how much you paid for it
u = User.objects.get(id=self.uid)
t = self.list.filter(user_item_rel__user__exact=u)
y = self.list.filter(buyer_item_rel__buyer__exact=u)
items = t | y
items = items.distinct()
u = User.objects.get(id=self.uid)
for t in items:
try:
t.price = t.user_item_rel_set.get(user=u).payment_amount
except:
t.price = -1 * t.buyer_item_rel_set.get(buyer=u).payment_amount
return items
并在另一个实例
for i in new_list:
if str(i.tag) not in x:
x[str(i.tag)] = 0
if houseMode == 0:
x[str(i.tag)] += float(i.user_item_rel_set.get(user__id__exact=self.uid).payment_amount)
else:
x[str(i.tag)] += float(i.price)
答案 0 :(得分:1)
您的模型中的一些其他代码会有所帮助,因为很难看到'items'查询集包含的内容。
无论如何我会尽力帮助......
因为您已经建模了用户和项之间的关系,所以当您只需选择您感兴趣的子集时,就无需迭代该查询集中的每个项目。
同样,我在应用逻辑方面遇到了一些困难,但我认为您的查询可以简化为这种性质:
# Find all the items where this user is the "user"
user_items = items.filter(user_item_rel_set__user=u)
# Find all the items where this user is the "buyer"
buyer_items = items.filter(user_item_rel_set__buyer=u)
我不太理解您为什么要在循环中将这些值分配给't.price',或者我会扩展该代码。
如果这对您的表现没有帮助,我建议dumping your SQL queries to the console,以便您可以准确了解ORM背后的情况。在这样的逻辑中,它不应该超过少数SQL语句来计算。
此外,在货币值附近的任何地方使用浮点数据类型(浮点数)通常是个坏主意。浮点数据类型通常用于性能比精度更重要的科学应用。如果你正在处理金钱,精确度几乎总是比性能更重要,所以你使用一个能够精确表示的数据类型,如decimal.Decimal 无处不在。
修改强>
鉴于评论,我建议使用“关系”对象而不是项目开始查询。由于您的示例没有告诉我该类的名称,我将假设它名为UserItem:
from django.db.models import Q
from decimal import Decimal
price = Decimal('0')
# Get all UserItems where this user is the user or buyer
interesting_items = UserItem.objects.filter((Q(user=u) | Q(buyer=u)))
for ii in interesting_items:
if ii.user == u:
price += ii.payment_amount
elif ii.buyer == u:
price -= ii.payment_amount
else:
assert False, "Oops, this shouldn't happen"
# Do something with 'price'...
Django“Q”工具可让您更加细致地查询。如果你需要根据项目的某些属性进行过滤,那么也要把它放在那里。
在您的示例中仍然让我感到困惑的部分是,当很明显许多用户将共享该项时,为什么要为项目对象分配“价格”。
修改2
如果你感兴趣的话,你也可以使用aggregation API让DBMS计算总和:
from django.db.models import Sum
buyer_price = UserItem.objects.filter(item=i, user=u).aggregate(
Sum('payment_amount'))['payment_amount__sum']