这是我的模型,用于存储新预订时特定时间的可用性
class TimeSlot(models.Model):
day = models.ForeignKey(
Day,
on_delete=models.CASCADE,
related_name="time"
)
booking = models.ForeignKey(
Booking,
on_delete=models.CASCADE,
related_name="time"
)
start_hour = models.TimeField()
end_hour = models.TimeField()
class Meta:
unique_together = [('end_hour', 'start_hour',)]
def clean(self):
pass
目前,它允许预订,即使那些在end_hour和start_hour方面被认为是重复的。我想防止空档,这样就不会在已经预订的范围之间放置新的预订。
谁能知道如何使用范围来做到这一点?
我认为问题是允许添加属于现有时间范围内的start_hour
和end_hour
。当然,unique_together
约束无法处理这个问题,因为它只处理唯一性而不是范围内的唯一性。相反,您可以重写模型clean
方法并在那里执行此验证:
from django.db.models import Q
from django.core.exceptions import ValidationError
class TimeSlot(models.Model):
day = models.ForeignKey(
Day,
on_delete=models.CASCADE,
related_name="time"
)
booking = models.ForeignKey(
Booking,
on_delete=models.CASCADE,
related_name="time"
)
start_hour = models.TimeField()
end_hour = models.TimeField()
class Meta:
unique_together = [('end_hour', 'start_hour',)]
def clean(self):
start_hour_in_range = Q(start_hour__lte=self.start_hour, end_hour__gte=self.start_hour)
end_hour_in_range = Q(start_hour__lte=self.end_hour, end_hour__gte=self.end_hour)
# Queryset that finds all clashing timeslots with the same day
queryset = self._meta.default_manager.filter(start_hour_in_range | end_hour_in_range, day=self.day)
if self.pk:
queryset = queryset.exclude(pk=self.pk) # Exclude this object if it is already saved to the database
if queryset.exists():
raise ValidationError('An existing timeslot clashes with the given one!')
接下来,如果您使用的是ModelForm
则会自动调用此方法,或者如果您不是,则可以调用instance.full_clean()
这将调用此方法以及模型上的所有其他清洁方法(clean_fields
和validate_unique
)。