Проверка перекрывающихся диапазонов TimeField

У меня есть эта модель:

class Task(models.Model):
    class Meta:
        unique_together = ("campaign_id", "task_start", "task_end", "task_day")

    campaign_id = models.ForeignKey(Campaign, on_delete=models.DO_NOTHING)
    playlist_id = models.ForeignKey(PlayList, on_delete=models.DO_NOTHING)
    task_id = models.AutoField(primary_key=True, auto_created=True)
    task_start = models.TimeField()
    task_end = models.TimeField()
    task_day = models.TextField()

Мне нужно написать проверочный тест, который проверяет, перекрывает ли вновь созданный диапазон времени задачи существующий в базе данных.

Например:

Задание с идентификатором 1 уже имеет время начала в 17:00 и заканчивается в 17:15 в субботу. Новая задача не может быть создана между временем начала и конца первой задачи. Где я должен написать этот тест и какой самый эффективный способ сделать это? Я также использую Сериализаторы DjangoRestFramework.

2 ответа

Решение

Когда вы получаете данные формы от пользователя, вы можете:

  • Проверьте соответствие полей: user task_start task_end, и предупредите пользователя, если нет.
  • Запрос (SELECT) базы данных для получения всех существующих задач, которые перехватывают время пользователя,

    • Упорядочить записи по task_start (ORDER BY),
    • Выберите только записи, которые подтверждают ваш критерий, иначе:

      • task_start <= пользователь task_start <= task_end, или,
      • task_start <= пользователь task_end <= task_end.
    • предупредить пользователя, если найдена хотя бы одна запись.

  • Все отлично:

    • Построить Task пример,

    • Сохраните это в базе данных.

    • Верните успех.

Детали реализации:

Task_start и task_end могут быть проиндексированы в вашей базе данных, чтобы сократить время выбора.

Я видел, что у вас также есть поле task_day (которое является ТЕКСТОМ).

Вы действительно должны рассмотреть возможность использования полей UTC DATETIME вместо TEXT, потому что вам нужно сравнить дату и время (а не только время): рассмотрите задачу, которая начинается в 23:30 и заканчивается в 00:45 на следующий день после…

Вот как я это решил. Это далеко не оптимально, но я ограничен Python 2.7 и Django 1.11, и я также новичок.

def validate(self, data):
    errors = {}
    task_start = data.get('task_start')
    task_end = data.get('task_end')
    time_filter = Q(task_start__range=[task_start, task_end]) 
    | Q(task_end__range=[task_start, task_end])
    filter_check = Task.objects.filter(time_filter).exists()
    if task_start > task_end:
        errors['error'] = u'End time cannot be earlier than start time!'
        raise serializers.ValidationError(errors)
    elif filter_check:
        errors['errors'] = u'Overlapping tasks'
        raise serializers.ValidationError(errors)
    else:
        pass
    return data
Другие вопросы по тегам