Django Delete all but last five of queryset

后端 未结 3 1288
[愿得一人]
[愿得一人] 2020-12-13 09:33

I have a super simple django model here:

class Notification(models.Model):
    message = models.TextField()
    user = models.ForeignKey(User)
    timestamp          


        
3条回答
  •  北荒
    北荒 (楼主)
    2020-12-13 10:05

    This is a bit old, but I believe you can do the following:

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

    It costs two hits, but avoids using the for loop with transactions middleware.

    The reason for using list(notes) is that Django creates a single query without it and, in Mysql 5.1, this raises the error

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

    By using list(notes), we force a query of notes, avoiding this. This can be further optimized to:

    notes = Notification.objects.filter(user=self.user)[:4].values_list("id", flat=True)  # only retrieve ids.
    Notification.objects.exclude(pk__in=list(notes)).delete()
    

提交回复
热议问题