使用混合\u属性对从其他列的值派生的时间列进行排序

2024-10-05 14:29:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试构建一个事件预订系统,作为学习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)

从下图可以看出,当我按“结束时间”排序时,排序顺序是错误的。它似乎仍在按开始时间排序。这里可能有什么问题

(无可否认,我仍然不了解混合动力车的特性。刚开始工作的时候,我以为我已经明白了,但现在看来我还是什么都不明白……)

sorting results


Tags: fromimportselfeventiddbdatetime
1条回答
网友
1楼 · 发布于 2024-10-05 14:29:40

end_time的表达式中,cls.event_id表示一个列,而不是一个值,因此查询最终在EventEventSlot之间执行隐式联接,并选择该联接的第一个结果。当然,这不是您想要的,但是对于EventSlot来说,您希望在SQL中找出相关Event的持续时间。这似乎是使用相关标量子查询的好地方:

@end_time.expression
def end_time(cls):
    # Get the duration of the related Event
    ev_duration = Event.query.\
        with_entities(Event.duration * 60).\
        filter(Event.event_id == cls.event_id).\
        as_scalar()
    # This will form a string concatenation SQL expression, binding the strings as
    # parameters to the query.
    duration = '+' + ev_duration.cast(db.String) + ' minutes'
    return db.func.time(cls.event_date, duration)

请注意,在查询上下文中访问属性时,查询不会运行,而是成为父查询的一部分

相关问题 更多 >