Parag Srivastava
Parag Srivastava

Reputation: 235

Limit the number of rows in a Django table

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

Answers (3)

Caiof
Caiof

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

Daniel Rosenthal
Daniel Rosenthal

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

karthikr
karthikr

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

Related Questions