Django, Фильтр запросов по нескольким перекрытиям временных интервалов

#django

Вопрос:

У меня есть модель рабочего и задачи.
У работника есть рабочее время (working_hours), а у Задачи есть время для работы (working_time).
Эти поля времени связаны с моделью timeInterval как ManyToManyField. Каждый интервал имеет время начала и окончания.
Я использовал ManyToManyField, потому что рабочий и задача могут иметь несколько интервалов в течение рабочего времени.
Например, работник может работать в промежутках с 07:00 до 12:00 и с 15:00 до 18:00. И задание должно быть выполнено с 13:00 до 17:00.

Мне нужно сделать запрос, какие задачи подходят для работника в рабочее время. Временные интервалы для работы должны перекрываться. Как я могу это сделать?

Я попытался получить интервалы рабочего времени от конкретного работника, а затем в цикле сформировать условие для фильтрации с использованием Q-объектов. Подобный этому:

 my_worker = Worker.objects.get(id=1)
my_worker_working_hours = my_worker.working_hours.all()
time_conditions = []

for interval in my_worker_working_hours:
    time_conditions.append(
        Q(
            Q(working_time__start__lte=interval.end) amp;
            Q(working_time__end__gte=interval.start)
        )
    )

suitable_task = Task.objects.filter(*time_conditions)

 

Это работает, если задача имеет только один интервал рабочего времени. В противном случае фильтр работает неправильно.

Мои модели:

 class Worker(models.Model):
    name = models.CharField(max_length=10)
    working_hours = models.ManyToManyField(TimeInterval)

class Task(models.Model):
    name = models.CharField(max_length=10)
    is_assigned = models.BooleanField(default=False)
    working_time = models.ManyToManyField(TimeInterval)

class TimeInterval(models.Model):
    start = models.TimeField()
    end = models.TimeField()
 

Обновить

Я использую SQLite. Я обнаружил, что в Django есть поле DateTimeRangeField для PostgreSQL. Решает ли это мою проблему? Я не очень хорошо знаком с PostgreSQL.

Комментарии:

1. Вы хотите найти задачи, которые лежат в интервале 1 ИЛИ интервале 2 ИЛИ…, да?

2. @AbdulAzizBarkat , Да, хотя бы один временной интервал должен перекрываться

Ответ №1:

Вы используете оператор или (канал) с Q объектами.

 suitable_tasks = Task.objects.none()
for interval in my_worker_working_hours:
    suitable_tasks |= Task.objects.filter(
        Q(working_time__start__lte=interval.end) amp; 
        Q(working_time__end__gte=interval.start))