2017-08-15 11 views
0

我有点奇怪的问题,我不能解释。Django使用分页删除查询集,没有捕获到集合的所有部分

我有一个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) 

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

我创建了一个管理命令来构建这些有序的对象的查询集,然后用分页程序删除与

我的命令看起来是这样的:

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() 

的问题我有在我用命令删除这些对象之后,仍然存在适合查询集参数但不会被删除的对象。所以,我必须运行该命令3次以正确查找并删除所有对象。

我首先想到我的日期范围只是奇怪的在DateTime的边缘,所以没有捕获在我的命令时间后不到1周的对象。事实并非如此,我已经从查询集中删除了created = ...过滤器,并得到了相同的结果。

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

+0

Paginator分页您的数据。我假设如果你删除'page_stale_objects',那么只会删除1个页面(这意味着你发现的对象数量超过了paginator的'per_page'值) –

回答

0

通过查询集分页被翻译成连续的LIMIT/OFFSET调用。所以,想想序列:

  • 得到与项目偏移量为0,并从偏移21

限制20

  • 删除这些项目
  • 得到下一个页面,即20项别急!一旦我们删除了第一组,查询集现在又从0开始。现在从0到20的项目被跳过。

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

  • +0

    嗯,是的,这是我开始通过一些更多的测试开始形成的。谢谢。 – rob

    0

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

    • 得到查询集
    • 排序这个查询集的ID
    • 拼版它
    • 从每个列表获取对象
    • 删除他们

    当你可能只是这样做:

    • 得到查询集
    • 删除查询集

    这将是一个巨大的性能提升,如果你有大量的对象。

    所以,我建议你只是这样做:

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

    希望它能帮助!

    +0

    这并不是真的试图回答核心问题,另外我已经显示了对查询集删除的理解。但是,为了回答你的问题,我这样做的原因有以下几个:1)在此过程中有更新或删除的其他相关对象,以及2)在大型查询集上使用delete()需要更长的时间删除而不是通过分页和删除一个子集。我已经测试了很多次,发现它适用于我所有的情况。 – rob