Django Удалить все, кроме последних пяти запросов
У меня есть супер простая модель django:
class Notification(models.Model):
message = models.TextField()
user = models.ForeignKey(User)
timestamp = models.DateTimeField(default=datetime.datetime.now)
Используя ajax, я проверяю новые сообщения каждую минуту. Я показываю только пять последних уведомлений пользователю в любое время. То, что я пытаюсь избежать, - это следующий сценарий.
Пользователь регистрируется и не имеет уведомлений. Пока окно пользователя завершено, он получает 10 новых сообщений. Поскольку я только показываю ему пять, неважно. Проблема возникает, когда пользователь начинает удалять свои уведомления. Если он удалит пять отображаемых, пять старых будут отображены в следующем вызове ajax или обновлении.
Я бы хотел, чтобы мой метод сохранения модели удалял все, кроме 5 самых последних объектов, когда новый сохраняется. К сожалению, вы не можете использовать [5:] для этого. Помощь?
ИЗМЕНИТЬ
Я пробовал это, который не работал должным образом (в методе сохранения модели):
notes = Notification.objects.filter(user=self.user)[:4]
Notification.objects.exclude(pk__in=notes).delete()
Я не мог найти шаблон в странном поведении, но через некоторое время тестирования он удалит только последний, когда будет создан новый. У меня нет идеи, почему это было бы. упорядочивание выполняется в модели Meta class (по убыванию времени). спасибо за помощь, но мой способ, кажется, единственный, который работает последовательно.
Ответы
Ответ 1
Это немного устарело, но я считаю, что вы можете сделать следующее:
notes = Notification.objects.filter(user=self.user)[:4]
Notification.objects.exclude(pk__in=list(notes)).delete() # list() forces a database hit.
Он стоит два раза, но избегает использования цикла for с промежуточным программным обеспечением транзакций.
Причина в том, что Django создает один запрос, а в Mysql 5.1 это вызывает ошибку
(1235, "This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'")
Используя list(notes)
, мы вынуждаем запрос 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
Используйте внутренний запрос, чтобы получить набор элементов, которые вы хотите сохранить, и затем фильтровать их.
objects_to_keep = Notification.objects.filter(user=user).order_by('-created_at')[:5]
Notification.objects.exclude(pk__in=objects_to_keep).delete()
Дважды проверьте это, прежде чем использовать его. Я обнаружил, что более простые внутренние запросы не всегда ведут себя так, как ожидалось. Странное поведение, которое я испытал, ограничено запросами, которые являются просто order_by и срезом. Поскольку вам придется фильтровать на пользователя, вы должны быть в порядке.
Ответ 3
вот как я это сделал.
notes = Notification.objects.filter(user=self.user)
for note in notes[4:]:
note.delete()
потому что я делаю это в методе сохранения, единственный способ, который цикл должен был запускать более одного раза, будет, если пользователь сразу получит несколько уведомлений. я не беспокоюсь о том, что это происходит (хотя может случиться, что это вряд ли будет достаточно, чтобы вызвать проблему).