0

我正在学习 Django。我正在尝试制作一个用于管理由简单元素组成的仓库的应用程序:

涉及的模型是交易、物品、仓库和房屋。

models.py

class Home(Model):
    name = models.CharField(max_length=255, verbose_name=_('name'),blank=False)

class Warehouse(Model):
    name = models.CharField(max_length=255, verbose_name=_('name'),blank=False)

class Item(Model):
    name = models.CharField(max_length=255, verbose_name=_('name'),
    whouse = models.ForeignKey('Warehouse', blank=True,null=True,on_delete=models.CASCADE, related_name='all_items')
    quantity    = models.PositiveSmallIntegerField(verbose_name=_('Quantity'), default=1, blank=False)
    @cached_property
    def count_remaining(self):
        remaining = self.quantity
        qs = self.transactions.all()
        if qs:
            out = qs.aggregate(Sum('quantity'))['quantity__sum']
            if out:
                remaining -= out
        return remaining


class Transaction(Model):
    item_field = models.ForeignKey('Item', blank=True,null=True,on_delete=models.CASCADE, related_name='all_transactions')
    home_field = models.ForeignKey('Home', blank=True,null=True,on_delete=models.CASCADE, related_name='all_transactions')
    quantity = models.PositiveSmallIntegerField(verbose_name=_('Quantity'), default=1, blank=False)

item_list.html(对于通用 ListView,带有qs=Item.objects.all()):

...
<table>
    <thead>
    <tr>
        <td>name</td>
        <td>quantity</td>
        <td>remaining items</td>
        <td>whouse</td>
    </tr>
    </thead>
    <tbody>
    {% for item in item_list %}
        <td>{{ item.name }}</td>
        <td>{{ item.quantity }}</td>
        <td>{{ item.count_remaining }}</td>
        <td>{{ item.whouse }}</td>
    {% endfor %}
    </tbody>
</table>
...

现在我的问题是,我的count_remaining方法被查询集中的每个对象调用一次,当 item_list 中有很多项目时,显然会导致数据库命中呈指数级增长。

如果我必须有一个页面在模板中显示仓库中的剩余项目,我如何才能在不过多访问数据库的情况下进行此算术运算?

4

1 回答 1

0

您可以exists()改用all()

@cached_property
def count_remaining(self):
    remaining = self.quantity
    # related_name='all_transactions'
    qs = self.all_transactions
    if qs.exists():
        out = qs.aggregate(Sum('quantity'))['quantity__sum']
        remaining -= out
    return remaining

django.db.models.query.QuerySet.exists

于 2021-01-18T20:21:32.723 回答