Разница во времени запроса истекла в Django ORM - PullRequest
2 голосов
/ 19 октября 2011

У меня есть простая модель для описания задачи и периода между ее выполнением:

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)

Я хочу иметь возможность запрашивать, используя ORM Django, какие задачи свежие и какие устарели, то есть те, которые должны быть выполнены согласно их расписанию.

В настоящее время я рассчитываю это для конкретной записи без ORM через:

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))

Как бы я сделал эквивалент с ORM Джанго, чтобы я мог запрашивать все свежие / устаревшие задачи одновременно?

например. Это, очевидно, не работает, но что-то вроде:

Tasks.objects.filter(Q(last_check_timestamp__isnull=True) || Q(last_check_timestamp + datetime.timedelta(seconds=schedule__interval_seconds)))

1 Ответ

3 голосов
/ 20 октября 2011

Мне недавно пришлось сделать похожий запрос. Я надеялся сделать это, используя F() объекты, но я не думаю, что это возможно, потому что timedelta опирается на столбец db (это было бы возможно, если бы schedule_interval_seconds была константой).

В итоге я выполнил запрос, используя ORM с extra(), и написал SQL для предложения where.

sql = "DATE_ADD(last_check_timestamp, INTERVAL schedule.interval_seconds SECOND) < DATE(NOW())"
Tasks.objects.filter(Q(last_check_timestamp__isnull=True) || Q(last_check_timestamp + datetime.timedelta(seconds=schedule__interval_seconds)))
tasks = Task.object.select_related('schedule').extra(where=[sql,]

Используется функция DATE_ADD ( Документы MySQL ). Возможно, вам придется настроить различные варианты SQL. select_related требуется, чтобы Django выполнял объединение с таблицей расписания.

Приведенное выше не выбирает задачи, где last_check_timestamp равно нулю. Я не думаю, что вы можете использовать комбинацию extra() и вашего Q объекта, но вы можете расширить оператор SQL.

sql = """last_check_timestamp is NULL or DATE_ADD(last_check_timestamp, INTERVAL schedule.interval_seconds SECOND) < DATE(NOW())"""
...