Проверка перекрывающихся диапазонов TimeField - PullRequest
0 голосов
/ 12 января 2019

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

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 ]

0 голосов
/ 13 января 2019

Вот как я это решил. Это далеко не оптимально, но я ограничен 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
0 голосов
/ 13 января 2019

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

  • Проверьте соответствие полей: пользователь task_start <пользователь <em>task_end и предупредите пользователя, если нет.
  • Запрос (ВЫБРАТЬ) базы данных для извлечения всех существующих задач, которые перехватывают время пользователя,

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

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

  • Все в порядке:

    • Построить Task экземпляр,

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

    • Возврат успеха.

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

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

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

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

...