我遇到了一些性能问题,因为我进行了大量查询调用,但我不确定如何减少这些调用。
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)
最佳答案
模型中的一些附加代码会有所帮助,因为很难看出“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 语句即可完成计算。
此外,在接近货币值的任何地方使用 float 据类型(float)通常是一个坏主意。 float 据类型通常用于性能比精度更重要的科学应用。如果您处理的是金钱,那么精度几乎总是比性能更重要,因此您使用能够精确表示的数据类型,例如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']
关于python - 优化这个 Django 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1691207/