Django Delete all but last five of queryset

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

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)