【问题标题】:Bulk update in django with calculations使用计算在 django 中批量更新
【发布时间】:2016-04-29 15:24:00
【问题描述】:

我的项目中有 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 分钟。

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

【问题讨论】:

    标签: python mysql django django-orm


    【解决方案1】:

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

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

    现在 Django 从 2.2 版开始带有 bulk_update 方法docs

    【讨论】:

      【解决方案2】:

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

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

      即使您拨打bulk_update,您仍然会循环所有商品,这就是您的流程缓慢的原因。

      编辑

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

      【讨论】:

      • 感谢您的回复。不幸的是,它不能以这种方式工作。 F 不允许加入字段。在这种情况下,看起来唯一的解决方案是原始 sql。有类似情况:stackoverflow.com/questions/21439031/…
      • 啊,是的,忘记了。原始sql就是这样。我几乎要哭了,因为它看起来离工作很近。
      • 它仍然对我有很大的帮助;)谢谢。
      • 好的。这不是一个好的答案,但至少我所说的循环缓慢是True。 :)
      猜你喜欢
      • 1970-01-01
      • 2016-11-18
      • 1970-01-01
      • 1970-01-01
      • 2012-09-21
      • 1970-01-01
      • 1970-01-01
      • 2019-07-04
      相关资源
      最近更新 更多