I have a simple model to describe a task and a period between executions of the task:
class Task(models.Model):
last_check_timestamp = models.DateTimeField(blank=True, null=True, db_index=True)
class TaskSchedule(models.Model):
task = models.OneToOneField(Task, blank=False, null=False, related_name='schedule')
interval_seconds = models.IntegerField(blank=False, null=False)
I want to be able to query, using Django’s ORM, which tasks are fresh and which are stale, meaning those that are due to be run according to their schedule.
I’m currently calculating this for a specific record without the ORM via:
import datetime
task = Task.objects.get(id=123)
fresh = task.last_check_timestamp is not None and datetime.datetime.now() < (task.last_check_timestamp + datetime.timedelta(seconds=task.schedule.interval_seconds))
How would I do the equivalent with Django’s ORM, so I could query all fresh/stale tasks at once?
e.g. This obviously doesn’t work, but something like:
Tasks.objects.filter(Q(last_check_timestamp__isnull=True) || Q(last_check_timestamp + datetime.timedelta(seconds=schedule__interval_seconds)))
I had to do a similar query recently. I was hoping to do it using
F()objects, but I don’t think this is possible, because the timedelta relies on a db column (it would be possible ifschedule_interval_secondswas a constant).In the end, I did the query using the ORM with
extra(), and wrote SQL for the where clause.This uses the
DATE_ADDfunction (MySQL docs). You may need to adjust for different flavours of SQL. Theselect_relatedis required so that Django does the join to the schedule table.The above does not select the tasks where
last_check_timestampis null. I don’t think you can use combine theextra()and yourQobject, but you can expand the SQL statement.