简体   繁体   English

使用计算在 Django 中批量更新

[英]Bulk update in django with calculations

I have 2 models in my project:我的项目中有 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)

The idea of such model is to speed up the search by price and have all goods in one currency.这种模型的想法是通过价格加快搜索速度,并以一种货币形式拥有所有商品。 Therefore I need some hook which will update all Goods in case exchange rate was updated.因此,我需要一些挂钩,以便在汇率更新时更新所有商品。

In raw sql it will looks like this在原始 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

Works pretty fast.工作得很快。 Though I tried to implement the same in django admin like this (using bulk-update ):尽管我尝试在 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()

It takes up to 20 minutes to update all records via django admin this way.以这种方式通过 django admin 更新所有记录最多需要 20 分钟。

What I am doing wrong?我做错了什么? What is the right way to update all the prices?更新所有价格的正确方法是什么?

This is purely untested, but it's sort of work in my mind:这纯粹是未经测试的,但在我看来这是一种工作:

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

Even you are calling bulk_update , you still looped through all goods, which is why your process is slow.即使您正在调用bulk_update ,您仍然遍历所有货物,这就是您的过程缓慢的原因。

Edit :编辑

This won't work because F() doesn't support joined fields.这将不起作用,因为F()不支持连接字段。 It can be done using raw query.可以使用原始查询来完成。

For the future readers: any call to good.currency in your code is hitting the database.对于未来的读者:在您的代码中对good.currency任何调用good.currency访问数据库。 Consider using select_related to fetch Currency and Good objects in one query:考虑使用select_related在一个查询中获取CurrencyGood对象:

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

Also now Django comes with bulk_update method since version 2.2 docs现在 Django 从 2.2 版文档开始也提供了bulk_update方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM