Running automated expiration date events

Visto 385 veces
Saltar al primer mensaje no leído

Rod Delaporte

no leída,
8 feb 2016, 14:08:598/2/16
a Django users
I have a field of a model that changes states but I need to automatically modify that value after an expiration datetime has come. Is there a way to do this?

Here is an example:

class Post(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
languages = (
            ('1', 'active'),
            ('2', 'inactive'),
        )
language = models.CharField(max_length=20, choices=languages, default='english')
duration = models.DurationField(blank=True, null=True)
expires = models.DateTimeField(blank=True, null=True)
updated_at = models.DateTimeField(auto_now=True)

@property
def active(self):
return self.expires > localtime(now())

def save(self, *args, **kwargs):
self.created_at = localtime(now())
self.expires = self.created_at + self.duration
return super(Post, self).save(*args, **kwargs)


The problem I have is that I have to call the active function property to check if it's True or False and I'm looking for a way that this can be done automatically so the database updates itself.
I've been thinking about Django-cron but I can't chose when to call the active function, this should be done for itself.

Is this possible?

Luis Zárate

no leída,
8 feb 2016, 17:48:468/2/16
a django...@googlegroups.com
Maybe with celery and Django celery you can do what you want.  There is a functionality called crontab that is manage by models with Django celery.  So you can create cron task that will call when you need with a reference to you model.

As an interesting problem, think in the moment of update you model if you use a cron task, specially when you change de date.
> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/87c2360f-b02c-42d4-ac33-d1dcdf4b852a%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

--
"La utopía sirve para caminar" Fernando Birri



James Schneider

no leída,
9 feb 2016, 4:23:159/2/16
a django...@googlegroups.com
What is the issue with calling the active property? Your model doesn't have what I'd presume to be a boolean field to store whether or not your model is in an 'active' state. Checking the 'active' state as you are doing now is far more accurate (down to the microsecond in most cases), rather than relying on a recurring maintenance job to 'mark' all of your expired model objects as expired in the database.

Doing so would a) cause management overhead by having a recurring job running that constantly scavenges all of your records to update a single boolean field, b) create an inconsistent state in your database between the time that a record actually expires, and your recurring database maintenance job to mark all of your records as expired. Depending on your use case, this would mean that models stay 'active' longer than they are supposed to, and c) add complication to your models to store a value that can be just as easily computed based on already-existing data. Is there a real difference between filter(is_expired=True) and filter(expires__lt(localtime(now())))? I'm betting that the two are basically equivalent in terms of search and process time, and you don't need to manage a separate field in your database with possibly stale information. Calling 'if self.active' would be the same as calling 'if not self.is_expired'. You can add model manager methods to automatically grab all expired or all active records.

Even so, you may still want to manually toggle Post objects on/off, so you would add a separate field like 'enabled', which would add a second condition to whether or not a post is shown (post must not be expired and must be enabled to be shown). Your 'active' property can easily be modified to make that determination. Model manager methods can also be easily drawn up to filter based on those conditions.

TL;DR; Having a separate field to track the expiry of an object is not ideal. If you add the 'enabled' toggle as I suggested, you could get away with having a recurring job (say, once a day) run through and mark expired posts as disabled, since they wouldn't be displayed anyway if you keep the conditions I mentioned earlier. Take advantage of model manager methods to filter out the posts you want (or don't want due to their expiration/enabled status), and look at management commands for running the recurring jobs. Cron on the host running a management command would likely be sufficient and much easier in this case, but Celery can probably perform the job just as well:


Side note, if you update an existing model, the created_at date is updated to the current timestamp. In general, created_at type dates are not usually modified after the initial insertion into the database. The updated_at field should be used for these operations. Otherwise you lose (accurate) historical tracking of your models.

-James
Responder a todos
Responder al autor
Reenviar
0 mensajes nuevos