Reputation: 235
I have a table in my models file and I want to design it such that there is a limit to ten rows in the table. When the limit is exceeded the oldest row will be deleted. For some context this is for a display on the front end that shows a user the ten most recent links they have accessed. I am new to Django so if anyone had a suggestion on how to do this, it would be greatly appreciated!
Upvotes: 7
Views: 5783
Reputation: 89
Improving a bit on @karthikr answer.
I also believe a post-save signal handler is the best way, but isolating the function in a class method and checking for the created
flag. If for example you want to keep a log of the last 1000 emails your system has sent:
from django.db import models
from django.db.models.signals import post_save
LOG_SIZE=1000
class EmailLog(models.Model):
"""Keeps a log of the 1000 most recent sent emails."""
sent_at = models.DateTimeField(auto_add_now=True)
message = models.TextField()
to_addr = models.EmailField()
@classmethod
def post_create(
cls,
sender,
instance: "EmailLog",
created: bool,
*args,
**kwargs
):
if created: # Indicates if it's a new object
qset = EmailLog.objects.order_by("sent_at") # Force ordering
if qset.count() > LOG_SIZE:
qset[0].delete()
post_save.connect(EmailLog.post_create, sender=EmailLog)
Upvotes: 0
Reputation: 1386
You could write a custom save
method that checks the length of YourObject.objects.all()
, and then deletes the oldest one when that length is equal to 10.
Something along the line of:
def save(self, *args, **kwargs):
if YourModel.objects.count() == 10:
objects[0].delete()
super(YourModel, self).save(*args, **kwargs)
Upvotes: 6
Reputation: 99650
In my opinion, you can use Signals. A post_save
in this case. This way, you keep the object creation and deletion logic separate.
Since you want the oldest
to be deleted, I am assuming you have a created
field in the model.
Once you save
,
def my_handler(sender, instance, **kwargs):
qs = MyModel.objects.order_by('created') #ensure ordering.
if qs.count() > 10:
qs[0].delete() #remove the oldest element
class MyModel(models.Model):
title = models.CharField('title', max_length=200)
created = models.DateTimeField(auto_add_now=True, editable=False)
post_save.connect(my_handler, sender=MyModel)
Of course, nothing stops you from using the pre_save
signal, but use it only if you are absolutely sure the save
method wont fail.
Upvotes: 4