python - 优化这个 Django 代码?

标签 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)

最佳答案

模型中的一些附加代码会有所帮助,因为很难看出“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/

相关文章:

python 转换 ls -l 样式日期

Python 3 pandas 使用字符串与正则表达式标记数据框中的数据

python - 运行 Django ./manage.py 时出现错误 "No such file or directory"

Django 批量更新/插入性能

jquery - django 1.3 中使用 jquery 和 $.post 进行 CSRF

python - 根据两个字段的总和过滤数据

python - 如何检查 django 表单数据是否为 ​​None、 ' '(空字符串)或 False

python - Pandas 重新采样并填充最后留下 NaN

python - Web应用程序用户名安全

python - Django 查询模型自创建以来 X 次