8👍
The most robust way to do this is typically a combination of filtering, and removing the items with a task you run every hour/day/week.
We thus can retrieve the items that are not yet expired with:
from django.db.models.functions import Now
stories = Story.objects.filter(expiration_time__lt=Now())
If you need to filter often, it might be more interesting to make a manager [Django-doc] for this.
from django.db import models
from django.db.models.functions import Now
class StoryManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(
expiration_time__lt=Now()
)
class Story(models.Model):
# …
xpiration_time = models.DateTimeField(db_index=True)
objects = StoryManager()
The db_index=True
part [Django-doc] will normally improve performance to filter expired objects.
Of course this does not remove the elements, it simply will not retrieve these (and thus if you filter these in the views, then you will not see these).
You can make a periodic task, for example a cronjob [wiki] that will run every day, week, month, hour to remove the elements. You can do this by defining a management command [Django-doc]:
# app_name/management/commands/remove_expired_stories.py
from django.core.management.base import BaseCommand
from django.db.models.functions import Now
from app_name.models import Story
class Command(BaseCommand):
help = 'Remove expired stories'
def handle(self, *args, **options):
Story._base_manager.filter(expiration_time__gte=Now()).delete()
Then you can manually run:
python3 manage.py remove_expired_stories
or you can schedule this task to run periodically. This is more robust: if for some reason the scheduler does no longer work, then the filtering will still prevent that you can see the Story
s that are expired. It is also simpler and more efficient than scheduling an expiration script per story, especially since if later the expiration time changes, it will be quite complicated to remove the scheduled items, and reschedule these.
1👍
I have learned that it simple solutions are often better than more beautiful, complex ones.
If this were me, I would run a scheduled process that runs once an hour and checks each row in the sql table. Then, check if post time was greater than 24 hours ago.
If you really want to get fancy, I would recommend Redis to create a scheduled process upon creation of the post. Schedule a task in 24 hours that deletes that particular post.
- [Django]-Problem installing pyscopg2 on Mac OS X
- [Django]-Import error: No module named 'Crypto' on Mac (Pycrypto is up-to-date)
- [Django]-Can't get django urls to work
0👍
I think willem van onsem is right… i mean his method
###LOGIC
time A i.e Now()---------somwhere in the future -------------------------timeB i.e expiration_time
if time A > time B its expired
if time A < time B its not expired
so with
...
expiration_time = models.DateTimeField(db_index= True,default=Now()+timedelta(days=1), editable = False)
in your models and in your manager
class StoryManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(
expiration_time__gt=Now()
)
then in the command/.py this
class Command(BaseCommand):
help = "clear expired messages"
def handle(self, *args, **options):
Story._base_manager.filter(expiration_time__lte=Now()).delete()
all should be well.