我正在尝试构建一个事件预订系统,作为学习python和web开发的辅助项目。下面是在我的项目中实现的两个模型。事件时隙表示为特定事件安排的时隙
型号
from app import db
from sqlalchemy import ForeignKey
from dateutil.parser import parse
from datetime import timedelta
from sqlalchemy.ext.hybrid import hybrid_property
class Event(db.Model):
event_id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, index=True, nullable=False)
duration = db.Column(db.Float, nullable=False)
price = db.Column(db.Float, nullable=False)
slots = db.relationship('EventSlot', cascade='all, delete', back_populates='event')
class EventSlot(db.Model):
slot_id = db.Column(db.Integer, primary_key=True)
event_date = db.Column(db.DateTime, nullable=False)
event_id = db.Column(db.Integer, ForeignKey('event.event_id'))
event = db.relationship('Event', back_populates='slots')
我提供了一个管理页面(Flask admin),供管理员用户查看数据库记录。在EventSlot页面上,我包括了“开始时间”和“结束时间”列,我想对它们进行排序。我将以下内容附加到EventSlot模型中:
class EventSlot(db.Model):
#...
## working as intended ##
@hybrid_property
def start_time(self):
dt = parse(str(self.event_date))
return dt.time().strftime('%I:%M %p')
@start_time.expression
def start_time(cls):
return db.func.time(cls.event_date)
## DOES NOT WORK: can display derived time, but sorting is incorrect ##
@hybrid_property
def end_time(self):
rec = Event.query.filter(Event.event_id == self.event_id).first()
duration = rec.duration * 60
derived_time = self.event_date + timedelta(minutes=duration)
dt = parse(str(derived_time))
return dt.time().strftime('%I:%M %p')
@end_time.expression
def end_time(cls):
rec = Event.query.filter(Event.event_id == cls.event_id).first()
duration = '+' + str(int(rec.duration * 60)) + ' minutes'
return db.func.time(cls.event_date, duration)
从下图可以看出,当我按“结束时间”排序时,排序顺序是错误的。它似乎仍在按开始时间排序。这里可能有什么问题
(无可否认,我仍然不了解混合动力车的特性。刚开始工作的时候,我以为我已经明白了,但现在看来我还是什么都不明白……)
在
end_time
的表达式中,cls.event_id
表示一个列,而不是一个值,因此查询最终在Event
和EventSlot
之间执行隐式联接,并选择该联接的第一个结果。当然,这不是您想要的,但是对于EventSlot
来说,您希望在SQL中找出相关Event
的持续时间。这似乎是使用相关标量子查询的好地方:请注意,在查询上下文中访问属性时,查询不会运行,而是成为父查询的一部分
相关问题 更多 >
编程相关推荐