django源码之bulk_update中生成器的应用

2022-01-06  本文已影响0人  Katou_Megumi

django的orm提供bulk_update批量更新记录的方法,
bulk_update(self, objs, fields, batch_size=None)
这里有个batch_size参数,作用是在待更新的objs数量过大时,提供分批更新的功能。

那么是怎么实现的呢?
很容易想到的是,对objs进行切片,每次取batch_size大小,然后对每个切片循环添加到update数组里。
那么django的源码是怎么做的呢?
我们在django\db\models\query.py中可以看到:

 def bulk_update(self, objs, fields, batch_size=None):
        """
        Update the given fields in each of the given objects in the database.
        """
        ······
        ······
        max_batch_size = connections[self.db].ops.bulk_batch_size(['pk', 'pk'] + fields, objs)
        batch_size = min(batch_size, max_batch_size) if batch_size else max_batch_size
        requires_casting = connections[self.db].features.requires_casted_case_in_updates
        batches = (objs[i:i + batch_size] for i in range(0, len(objs), batch_size))
        updates = []
        for batch_objs in batches:
        ······
            updates.append(([obj.pk for obj in batch_objs], update_kwargs))
        ······

这里最核心的代码是这一句:
batches = (objs[i:i + batch_size] for i in range(0, len(objs), batch_size))
初看这段代码有点奇怪,这里是怎么实现分批更新的呢,就在这里,这里batches是一个生成器generator
只需要把一个列表生成式的[]改成()就可以创建一个生成器,这样我们无需把完整的objs按照batch_size分割成一个个切片执行update,而是直接对batches循环就可以源源不断生成list。

我们在遇到类似场景时可以借鉴这种技巧。

上一篇 下一篇

猜你喜欢

热点阅读