Проверка перекрывающихся диапазонов 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