代码之家  ›  专栏  ›  技术社区  ›  Brandon Henry

Django删除queryset中除最后五个之外的所有内容

  •  24
  • Brandon Henry  · 技术社区  · 16 年前

    我这里有一个超级简单的django模型:

    class Notification(models.Model):
        message = models.TextField()
        user = models.ForeignKey(User)
        timestamp = models.DateTimeField(default=datetime.datetime.now)
    

    使用ajax,我每分钟都会检查新消息。我在任何时候都只向用户显示最近的五个通知。我试图避免的是以下情况。

    编辑

    我尝试了这个方法,但没有按预期效果(在模型的保存方法中):

        notes = Notification.objects.filter(user=self.user)[:4]
        Notification.objects.exclude(pk__in=notes).delete()
    

    我在奇怪的行为中找不到模式,但经过一段时间的测试,它只会在创建新模式时删除最近的模式。我不知道为什么会这样。排序在模型的元类中进行(通过时间戳降序)。谢谢你的帮助,但我的方式似乎是唯一一种始终如一的方式。

    3 回复  |  直到 16 年前
        1
  •  49
  •   Jorge Leitao    8 年前

    这有点陈旧,但我相信您可以做到以下几点:

    notes = Notification.objects.filter(user=self.user)[:4]
    Notification.objects.exclude(pk__in=list(notes)).delete()  # list() forces a database hit.
    

    它需要两次点击,但避免使用for循环和事务中间件。

    list(notes) Django创建了一个没有它的查询,在Mysql 5.1中,这会引发错误

    (1235, "This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'")
    

    利用 清单(附注) notes ,避免这种情况。

    notes = Notification.objects.filter(user=self.user)[:4].values_list("id", flat=True)  # only retrieve ids.
    Notification.objects.exclude(pk__in=list(notes)).delete()
    
        2
  •  12
  •   istruble kalyan    16 年前

    使用内部查询获取要保留的项目集,然后对其进行筛选。

    objects_to_keep = Notification.objects.filter(user=user).order_by('-created_at')[:5]
    Notification.objects.exclude(pk__in=objects_to_keep).delete()
    

    使用前请仔细检查。我发现更简单的内部查询并不总是像预期的那样运行。我所经历的奇怪行为仅限于仅是一个订单和一个切片的查询集。因为您必须根据用户进行筛选,所以应该可以。

        3
  •  9
  •   Brandon Henry    16 年前

    我就是这样做的。

        notes = Notification.objects.filter(user=self.user)
        for note in notes[4:]:
            note.delete()
    

    因为我是在save方法中这样做的,所以循环必须多次运行的唯一方法是,如果用户同时收到多个通知。我并不担心这种情况的发生(虽然可能发生,但不太可能造成问题)。