Django QuerySet фильтр по диапазону с помощью поля DateTimeField

Я пытался исправить свой метод queryset, проверил несколько ответов на Stackoverflow, но так и не смог этого сделать.

В основном я хочу проверить мою форму, так что когда есть урок в пределах определенного диапазона, студент не может предложить этот конкретный диапазон времени для своего урока.

Проблема в том, что когда я пытаюсь найти набор запросов, содержащий DateTimeField, который существует, я получаю пустой набор запросов:

Моя модель:

class Lesson(models.Model):
    student = models.ForeignKey(User, on_delete=models.CASCADE)
    subject = models.ForeignKey(Classroom, on_delete=models.CASCADE)
    description = models.CharField(max_length = 200)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    accepted = models.BooleanField(default=False)

Метод в форме:

def clean(self):
    cleaned_data = super().clean()
    lesson_start_time = cleaned_data.get('start_time')
    lesson_end_time = cleaned_data.get('end_time')
    
    queryset = Lesson.objects.filter(start_time__range=(lesson_start_time,lesson_end_time))
    print(lesson_start_time) #2022-08-23 15:44:00+00:00
    print(lesson_end_time) #2022-08-23 15:36:00+00:00
    print(queryset) # <QuerySet []>
    
    if lesson_end_time < lesson_start_time:
        raise ValidationError("End time cannot be lower than start time!")

И в этом диапазоне наверняка есть объект урока.

На данный момент я знаю, что для фильтрации DateTimeField по диапазону требуется что-то еще, но все, что я пробовал, не работает (например: Django - Filter objects by DateTimeField with a date range).

Не могли бы вы мне помочь?

Это возможно: два диапазона могут пересекаться, без того, чтобы время начала или время окончания находилось в пределах "диапазона" другого объекта. Например, если второй объект полностью содержится первым объектом.

You can fix this by first determining when two ranges do not overlap. Two ranges [s1, e1] and [s2, e2] do not overlap if s1< e2, or e1<s2. We can negate this expression to know when two intervals overlap: s1≤e2, and e1≥s2.

Таким образом, это означает, что мы можем проверить это с помощью:

def clean(self):
    cleaned_data = super().clean()
    start = cleaned_data['start_time']
    end = cleaned_data['end_time']

    queryset = Lesson.objects.exclude(pk=self.instance.pk).filter(
        start_time__lte=end, end_time__gte=start
    )
    if end <= start:
        raise ValidationError('End time cannot be lower than start time!')
    if queryset.exists():
        raise ValidationError('There is an item with overlap!')
    return cleaned_data
Вернуться на верх