2009-11-06 84 views
1

我有一些性能问题,因为我做了很多查询调用,我不知道如何减少。优化此django代码?

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) 

回答

1

从模型中一些额外的代码会有所帮助,因为它很难看什么“项目”的查询集包含的内容。

我会尽力帮助反正...

因为您建模用户和项目之间的关系,也没有必要每个项遍历在查询集时,你可以简单地选择那些子集对你有意思。

同样,我在下面的应用程序逻辑有点困难,但我认为你的查询可以减少这种性质的东西:

# 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)通常是一个坏主意。浮点数据类型通常用于性能比精度更重要的科学应用。如果你在处理金钱问题,精确度几乎总是比性能更重要,所以你使用的数据类型能够精确表示,如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'] 
+0

因此项目具有一定的价格,它的M2M关系(user_item_rel)具有多少用户为该项目付费。我有一个用户参与的项目清单(具体是你的代码),我试图检索用户为每个项目支付了多少,但是如果不为每一个项目敲击数据库,我都无法做到这一点。 – victor 2009-11-07 01:16:33

+0

因此'payment_amount'字段存储在用户和项目之间的关系对象上?我认为M2M关系有其自己的模型? – 2009-11-07 01:48:02

+0

是的,就是这样。 – victor 2009-11-07 01:57:18