Django使用分页删除查询集,而不是捕获集合的所有部分

时间:2017-08-15 06:15:26

标签: python django django-queryset

我有一个奇怪的问题,我无法解释。

我有一个django项目,周围有一些旧的陈旧物品。例如,假设我的对象看起来像这样:

class blog_post(models.Model):
    user_account = models.ForeignKey('accounts.Account')
    text = models.CharField(max_length=255)
    authors = models.ManyToManyField(author)
    created =  models.DateTimeField(blank=True, null=True)

这不是我的模型的精确副本,但足够接近。

我已经创建了一个管理命令来构建这些对象的有序查询集,然后使用Paginator进行删除

我的命令看起来像这样:

all_accounts = Account.objects.all()
for act in all_accounts.iterator():
    stale_objects = blog_post.objects.filter(user_account=act, 
    created=django.utils.timezone.now() - datetime.timedelta(days=7))

    paginator = Paginator(stale_objects.order_by('id'), 100)
    for page in range(1, paginator.num_pages + 1):
        page_stale_objects = blog_post.objects.filter(id__in=paginator.page(page).object_list.values_list('id'))
        page_stale_objects.delete()

我遇到的问题是,在使用my命令删除这些对象后,仍然存在符合查询集参数但未删除的对象。因此,我必须运行命令3次以正确查找和删除所有对象。

我首先想到我的日期范围在日期时间的边缘非常奇怪,所以在命令时间过去1周之后不久就捕捉到对象。事实并非如此,我已从查询集中删除了created = ...过滤器,并且结果相同。

为什么我的查询集在第一次运行此命令时没有捕获所有对象?没有多余的物体,最多约30,000行。

2 个答案:

答案 0 :(得分:1)

通过查询集进行分页会转换为连续的LIMIT / OFFSET调用。所以,想想序列:

  • 获取偏移0和限制20
  • 的项目
  • 删除这些项目
  • 获取下一页,即来自offset 21
  • 的20项

但是等等!删除第一个集后,查询集现在再次从0开始。现在从0到20的项目被跳过。

解决方案是,不要这样做。分页用于显示对象,而不是删除它们。

答案 1 :(得分:0)

如果您只想删除查询集,我不明白为什么要使用Paginator。如果我错了,请纠正我,但看起来你正在做以下事情:

  • 获取查询集
  • 按ID
  • 对此查询集进行排序
  • 将它分页
  • 从每个列表中获取对象
  • 删除它们

当你可以这样做时:

  • 获取查询集
  • 删除查询集

如果您有很多对象,这将是一个巨大的性能提升。

所以,我建议你这样做:

stale_objects = blog_post.objects.filter(...)
stale_objects.delete()

希望它有所帮助!