在SQLAlchemy和Postgres中查询重叠的时间范围



我使用Flask SQLAlchemy来描述Postgres数据库。三个相关的表格如下(部分(:

from sqlalchemy.dialects.postgresql import TSTZRANGE
class Shift(Base):
__tablename__ = "shifts"
id = db.Column(db.Integer, primary_key=True)
hours = db.Column(TSTZRANGE, nullable=False)
class Volunteer(Base):
__tablename__ = "volunteers"
id = db.Column(db.Integer(), primary_key=True)
shifts = db.relationship(
"Shift",
secondary="shift_assignments",
backref=db.backref("volunteers", lazy="dynamic"),
)
class ShiftAssignment(Base):
__tablename__ = "shift_assignments"
__table_args__ = (db.UniqueConstraint('shift_id', 'volunteer_id', name='_shift_vol_uc'),)
id = db.Column(db.Integer, primary_key=True)
shift_id = db.Column("shift_id", db.Integer(), db.ForeignKey("shifts.id"))
volunteer_id = db.Column(
"volunteer_id", db.Integer(), db.ForeignKey("volunteers.id")
)

现在,我将一个Volunteer分配给新的Shift,并希望确保vol没有同时提交给不同的Shift

我在Volunteer实例方法中尝试过,但不起作用:

new_shift = db.session.get(Shift, new_shift_id)
if new_shift not in self.shifts:
for shift in self.shifts:
overlap = db.session.scalar(shift.hours.overlaps(new_shift.hours))

这导致以下异常:

'DateTimeTZRange' object has no attribute 'overlaps'

看起来我可能根本不应该通过迭代列表来完成这项工作,而是应该直接查询数据库来进行日期重叠计算。所以我想我需要加入志愿者和轮班,然后过滤,看看是否有轮班与目标轮班重叠。但我不知道如何做到这一点,overlaps和它的RangeOperators朋友的例子真的很少。

请帮忙。

这比我做的要容易得多。同样,这是在Volunteer实例方法中。

new_shift = db.session.get(Shift, new_shift_id)
overlapping_shift = (
db.session.query(Shift, ShiftAssignment)
.join(ShiftAssignment)
.filter(ShiftAssignment.volunteer_id == self.id)
.filter(Shift.hours.overlaps(new_shift.hours))
.first()
)
if overlapping_shift:
print("overlap found")

请注意,查询返回一个(Shift,ShiftAssignment(元组。我们将两个适当的表连接起来,然后过滤两次,留下分配给当前志愿者的任何重叠轮班。

最新更新