通过计算在django中批量更新

时间:2016-01-22 22:01:09

标签: python mysql django django-orm

我的项目中有2个模型:

class Currency(models.Model):
    title = models.CharField(max_length=100, unique=True)
    value = models.FloatField()

class Good(models.Model):
    name = models.CharField(max_length=100)
    slug = SlugField(max_length=100, unique=True)
    cost_to_display = models.IntegerField(default=0)
    cost_in_currency = models.IntegerField()
    currency = models.ForeignKey(Currency)

这种模式的想法是按价格加速搜索,并将所有商品都放在一种货币中。 因此我需要一些钩子来更新所有商品,以防更新汇率。

在原始sql中它看起来像这样

mysql> update core_good set cost_to_display = cost_in_currency * (select core_currency.value from core_currency where core_currency.id = currency_id ) ;
Query OK, 663 rows affected (0.10 sec)
Rows matched: 7847  Changed: 663  Warnings: 0

工作得非常快。虽然我试图在django admin中实现相同的功能(使用bulk-update):

def save_model(self, request, obj, form, change):
    """Update rate values"""
    goods = Good.objects.all()
    for good in goods:
        good.cost_to_display = good.cost_in_currency * good.currency.value
    bulk_update(goods)
    obj.save()

通过django admin以这种方式更新所有记录最多需要20分钟。

我做错了什么?更新所有价格的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

这纯粹是未经测试的,但在我看来这是一种工作:

from django.db.models import F
Good.objects.all().update(cost_to_display=F('cost_in_currenty') * F('currency__value'))

即使您正在呼叫bulk_update,您仍然会查看所有商品,这就是您的流程进展缓慢的原因。

修改

这不起作用,因为F()不支持已连接的字段。可以使用原始查询来完成。

答案 1 :(得分:0)

对于未来的读者:在您的代码中对 good.currency 的任何调用都会访问数据库。考虑使用 select_related 在一个查询中获取 CurrencyGood 对象:

goods = Good.objects.select_related('currency')

现在 Django 也带有 bulk_update 方法,因为版本 2.2 docs