Django Paginator with bulk_update只更新奇数页

inkz8wg9  于 2023-08-08  发布在  Go
关注(0)|答案(1)|浏览(101)

我有两个表,大约有100万行,在其中一个表中,我添加了一个新的迁移,向其中一个表添加了两个新列,这需要一些计算来添加它们的值。
我所做的是一个获取该表中所有行的命令,并使用块大小为1000的Paginator,在添加新值之后,我执行bulk_update。
问题是,只有奇数页被更新,偶数页保持空值。我从1000页开始更新,然后我需要再次运行,只更新500页,等等。我也测试了10块,问题仍然存在。这个代码有什么问题吗?

def add_values_to_columns(foo):
    foo.col1=...
    foo.col2=...

class Command(BaseCommand):
    def handle(self, *args, **options):
        try:
            queryset = Foo.objects.all() \
                .filter(col1__isnull=True, col2__isnull=True) \
                .order_by("id") \
                .select_related("bar")

            chunk_size = 1000

            paginator = Paginator(queryset, chunk_size)
            pages = paginator.page_range
            number_pages = pages[-1]

            for page_number in pages:
                page = paginator.page(page_number)
                updated_rows = []

                for foo in page.object_list:
                    add_values_to_columns(foo)
                    updated_rows.append(foo)

                Foo.objects.bulk_update(updated_rows, ["col1", "col2"])
        except Exception as e:
            self.stdout.write(e)

字符串

wkftcu5l

wkftcu5l1#

paginator是 lazy,事实上这是paginator的主要用例:以在需要时检索记录的子集。
因此,如果您的页面大小为10,您将获得前十个项目,更新这些项目,使其不再满足您的分页器的条件,并获得下一页,您将跳过10个元素,但这些元素与前一页不同:由于您更新了一些行,分页器中的前十个项目将发生更改,因此它确实将跳过十个项目。
我们可以使用迭代器

class Command(BaseCommand):
    def handle(self, *args, **options):
        chunk_size = 1000
        queryset = (
            Foo.objects.all()
            .filter(col1__isnull=True, col2__isnull=True)
            .order_by('id')
            .select_related('bar')
            .iterator(chunk_size=chunk_size)
        )

        updated_rows = []
        for foo in queryset:
            add_values_to_columns(foo)
            updated_rows.append(foo)
            if len(updated_rows) > chunk_size:
                Foo.objects.bulk_update(updated_rows, ['col1', 'col2'])
                updated_rows = []

字符串
因此,这将与游标一起工作,以获取记录并收集要更新的对象。

相关问题