Django中如何检查时间段重叠,避免Slot模型时段冲突
实现方案
核心判断逻辑
两个时段[start1, end1)和[start2, end2)重叠的充要条件是 start1 < end2 AND start2 < end1,你的需求里时段端点相等(如end1 = start2)属于合法不重叠场景,正好符合该判断规则。
完整代码实现
我们直接在Django模型层添加校验逻辑,覆盖所有写入场景的校验需求:
from django.db import models from django.core.exceptions import ValidationError from django.db.models import Q class Slot(models.Model): start_time = models.TimeField() end_time = models.TimeField() def clean(self): # 基础校验:确保开始时间早于结束时间 if self.start_time >= self.end_time: raise ValidationError("结束时间必须晚于开始时间") # 重叠时段查询 overlapping_slots = Slot.objects.filter( Q(start_time__lt=self.end_time) & Q(end_time__gt=self.start_time) ).exclude(pk=self.pk) # 排除当前正在编辑的记录,避免更新时自己和自己冲突 if overlapping_slots.exists(): raise ValidationError("该时段与已有时段重叠,无法保存") def save(self, *args, **kwargs): # 保存前自动触发校验,无需手动调用full_clean self.full_clean() super().save(*args, **kwargs)
逻辑验证
以你举的例子测试:
- 已存在时段
02:00:00 - 03:00:00 - 新增
01:00:00 - 02:00:00:已有记录的start_time=02:00:00不小于当前end_time=02:00:00,查询不到重叠记录,校验通过 - 新增
03:00:00 - 04:00:00:已有记录的end_time=03:00:00不大于当前start_time=03:00:00,查询不到重叠记录,校验通过 - 新增
02:30:00 - 03:30:00:可以查询到重叠记录,校验失败抛出异常
扩展说明
如果业务存在多维度隔离规则(比如不同日期、不同会议室的时段互不影响),只需要在filter查询中添加对应的维度过滤条件即可,示例:
# 假设模型新增了date、room_id字段,仅校验同日期同会议室的时段重叠 overlapping_slots = Slot.objects.filter( date=self.date, room_id=self.room_id, Q(start_time__lt=self.end_time) & Q(end_time__gt=self.start_time) ).exclude(pk=self.pk)
内容的提问来源于stack exchange,提问作者raj-kapil
相关产品推荐
相关产品推荐

