优化这个django代码?

时间:2009-11-06 23:23:38

标签: python 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 个答案:

答案 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']