Python 用于有序查询集的Django查询集迭代器

Python 用于有序查询集的Django查询集迭代器,python,django,django-models,Python,Django,Django Models,我想使用queryset迭代器对大型数据集进行迭代。Django为此提供了iterator(),但每次迭代都会影响数据库。我发现下面的代码是分块迭代的- def queryset_iterator(queryset, chunksize=1000): ''''' Iterate over a Django Queryset ordered by the primary key This method loads a maximum of chunksize (defa

我想使用queryset迭代器对大型数据集进行迭代。Django为此提供了
iterator()
,但每次迭代都会影响数据库。我发现下面的代码是分块迭代的-

  def queryset_iterator(queryset, chunksize=1000):
    '''''
    Iterate over a Django Queryset ordered by the primary key
    This method loads a maximum of chunksize (default: 1000) rows in it's
    memory at the same time while django normally would load all rows in it's
    memory. Using the iterator() method only causes it to not preload all the
    classes.
    Note that the implementation of the iterator
    does not support ordered query sets.
    '''
    pk = 0
    last_pk = queryset.order_by('-pk').values_list('pk', flat=True).first()
    if last_pk is not None:
        queryset = queryset.order_by('pk')
        while pk < last_pk:
            for row in queryset.filter(pk__gt=pk)[:chunksize]:
                pk = row.pk
                yield row
            gc.collect()
def queryset_迭代器(queryset,chunksize=1000):
'''''
迭代按主键排序的Django查询集
此方法在其存储空间中最多加载chunksize(默认值:1000)行
django通常会同时加载内存中的所有行
记忆。使用迭代器()方法只会导致它不预加载所有
上课。
请注意,迭代器的实现
不支持有序查询集。
'''
pk=0
last_pk=queryset.order_by('-pk')。values_list('pk',flat=True)。first()
如果最后一个_pk不是无:
queryset=queryset.order\u by('pk')
当pk

这适用于无序查询集。是否有任何解决方案/解决方法可以在有序查询集上执行此操作?

这是我的,带有排序功能

顺便说一句,您正在使用的迭代器在过程中修改queryset项时有一个“永久循环”:删除或添加,甚至一个项

下面的迭代器对最后一个_pk没有无用的查询

def queryset_iterator(queryset, chunksize=10000, key=None):
    key = [key] if isinstance(key, str) else (key or ['pk'])
    counter = 0
    count = chunksize
    while count == chunksize:
        offset = counter - counter % chunksize
        count = 0
        for item in queryset.all().order_by(*key)[offset:offset + chunksize]:
            count += 1
            yield item
        counter += count
        gc.collect()

我认为你应该接受Igor的答案。无限循环的好捕捉和很好的解决方案。非常有用!对于子模型使用
bulk\u create
时,这将不起作用。例如,如果您正在使用这种方法进行迭代,并且在迭代过程中,您将对iterable的子模型执行
bulk\u create
。因此,在第二次迭代中尝试限制和偏移将导致一个空查询集。