Django Eliminar todos pero últimos cinco de queryset

Tengo un modelo django super simple aquí:

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

Usando ajax, reviso nuevos mensajes cada minuto. Solo muestro las cinco notificaciones más recientes al usuario en cualquier momento. Lo que estoy tratando de evitar, es el siguiente escenario.

El usuario inicia sesión y no tiene notificaciones. Mientras la ventana del usuario está abierta, recibe 10 mensajes nuevos. Ya que solo le estoy mostrando cinco, no es gran cosa. El problema ocurre cuando el usuario comienza a borrar sus notificaciones. Si elimina los cinco que se muestran, los cinco más antiguos se mostrarán en la próxima llamada o actualización de ajax.

Me gustaría que el método de guardado de mi modelo elimine todo menos los 5 objetos más recientes cada vez que se guarde uno nuevo. Desafortunadamente, no puedes usar [5:] para hacer esto. ¿Ayuda?

EDITAR

Intenté esto que no funcionó como se esperaba (en el método de guardado del modelo):

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

No pude encontrar un patrón en un comportamiento extraño, pero después de un tiempo de prueba, solo eliminaría el más reciente cuando se creara uno nuevo. No tengo idea de por qué esto sería. el orden se realiza en la clase Meta del modelo (por marca de tiempo descendente). Gracias por la ayuda, pero mi camino parece ser el único que funciona de manera consistente.

Esto es un poco viejo, pero creo que puedes hacer lo siguiente:

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

Cuesta dos aciertos, pero evita usar el bucle for con transacciones de middleware.

La razón para usar la list(notes) es que Django crea una sola consulta sin ella y, en Mysql 5.1, esto genera el error

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

Al usar la list(notes) , forzamos una consulta de notes , evitando esto. Esto puede optimizarse aún más para:

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

Use una consulta interna para obtener el conjunto de elementos que desea conservar y luego filtre sobre ellos.

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

Comprueba esto antes de usarlo. He descubierto que las consultas internas más simples no siempre se comportan como se espera. El extraño comportamiento que he experimentado se ha limitado a los conjuntos de consultas que son solo un order_by y un sector. Ya que tendrá que filtrar por usuario, debería estar bien.

Así es como terminé haciendo esto.

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

porque estoy haciendo esto en el método de guardar, la única forma en que el bucle tendría que ejecutarse más de una vez sería si el usuario recibiera varias notificaciones a la vez. No me preocupa que eso suceda (aunque puede suceder, no es probable que sea suficiente para causar un problema).