Sqlalchemy按日期过滤

时间:2016-11-09 01:45:56

标签: python sqlalchemy

我正在尝试构建一个过滤酒店价格列表的查询。我只想显示今天和未来的酒店预订。我构建的查询在下面但不过滤结果。我做错了什么?

hotels = db.session.query(Hotel).\
    join(Location).\
    join(Rate).\
    filter(Location.city == city).\
    filter(Rate.arrive > datetime.utcnow())

对于背景,我的模型看起来像这样:

class Location(Base):
    __tablename__ = 'locations'

    id = Column(Integer, primary_key=True)
    city = Column(String(50), nullable=False, unique=True)

    hotels = relationship('Hotel', back_populates='location')


class Hotel(Base):
    __tablename__ = 'hotels'

    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False, unique=True)
    phone_number = Column(String(20))
    parking_fee = Column(String(10))
    location_id = Column(Integer, ForeignKey('locations.id'), nullable=False)

    location = relationship('Location', back_populates='hotels')
    rates = relationship('Rate', back_populates='hotel', order_by='Rate.arrive')


class Rate(Base):
    __tablename__ = 'rates'

    id = Column(Integer, primary_key=True)
    price = Column(Numeric(6, 2))
    arrive = Column(Date, nullable=False)
    link = Column(String(500), nullable=False)
    updated = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
    hotel_id = Column(Integer, ForeignKey('hotels.id'), nullable=False)

    hotel = relationship('Hotel', back_populates='rates')

编辑: 以下是一些示例数据:

Date: Friday, Sep 9

Rate: 299.25

Date: Sunday, Sep 11

Rate: 261.75

Date: Monday, Sep 12

Rate: 261.75

Date: Tuesday, Sep 13

Rate: 261.75

Date: Sunday, Sep 18

删除过滤器(Rate.arrive> datetime.utcnow())不会更改数据。每次运行查询时输出都相同。

1 个答案:

答案 0 :(得分:1)

选项零是在您加载酒店后应用费率过滤器,但这会生成其他查询,并且不需要。

定义稍后使用的过滤器:

city = 'mumbai'
arrive = datetime.date.today()

选项-1:在初始查询中加载感兴趣的Rate

query = (
    session.query(Hotel, Rate)  # this query will return pairs (Hotel, Rate)
    .join(Location)
    .join(Rate)
    .filter(Location.city == city)
    .filter(Rate.arrive > arrive)
)

# one could use the results directly as (Hotel, Rate) pairs
# but we can also convert to the format: {hotel: rates}
from collections import defaultdict
hotels_list = defaultdict(list)
for h, r in hotels:
    hotels_list[h].append(r)

# and print:
for hotel, rates in hotels_list.items():
    print('', hotel)
    for rate in rates:
        print('  ', rate)

选项-2:欺骗关系Hotel.rates

我们正在使用contains_eager

hotels = (
    session.query(Hotel)
    .join(Location)
    .join(Rate)
    .options(contains_eager(Hotel.rates))  # this is the key
    .filter(Location.city == city)
    .filter(Rate.arrive > arrive)
)


for hotel in hotels:
    print('', hotel)
    for rate in hotel.rates:  # this now contains only sub-list, so be careful
        print('  ', rate)