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