Python SQLAlchemy - 更新子模型时更新父模型上的时间戳

问题描述 投票:0回答:2

我创建了两个模型,

Basket
BasketItem
,如下所示。一个篮子可以有很多篮子项目,因此我使用外键来创建这种关系。

您可以看到

Basket
模型有一个
updated_at
字段,其中保存了购物篮上次更新时间的时间戳。我希望在添加、删除或更新
BasketItem
时更新此字段。

我添加了一个事件监听器,但我的解决方案看起来不太优雅。有更好的方法吗?

class Basket(Base):
    __tablename__ = "baskets"

    id = Column(String(45), primary_key=True, default=uuid4)
    shop = Column(String(45), nullable=False)
    currency_code = Column(String(3), nullable=False)
    total = Column(String(15), nullable=False, default=0)
    status = Column(Enum("open", "closed"), nullable=False, default="open")
    created_at = Column(DateTime, default=datetime.datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.utcnow)

    items = relationship("BasketItem", backref="basket")


class BasketItem(Base):
    __tablename__ = "basket_items"

    basket_id = Column(String(45), ForeignKey('baskets.id'), primary_key=True)
    product_url = Column(String(90), nullable=False, primary_key=True)
    quantity = Column(Integer, nullable=False)

@event.listens_for(BasketItem, 'after_insert')
@event.listens_for(BasketItem, 'after_update')
@event.listens_for(BasketItem, 'after_delete')
def basket_item_change(mapper, connection, target):
    db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
    basket = db_session.query(Basket).get(target.basket_id)
    basket.updated_at = datetime.datetime.utcnow()
    db_session.commit()
python sqlalchemy foreign-key-relationship
2个回答
1
投票

我认为使用事件侦听器很好,但你可以执行如下操作。当您添加新的购物篮项目时,我确信您首先查询父级,然后将此子级添加到该父级。如果是的话:

basket = Basket.query.get(id)
if basket:
    basket.update()
    # you can perform delete or update too
    item = BasketItem(basket=basket, ...)
    db.session.add(item)
    db.session.commit()

class Basket(db.Model):
    ...
    def update(self):
        self.updated_at  = datetime.utcnow()
        db.session.add(self)
        db.session.commit()

0
投票

老问题,但这个用例似乎仍然没有充分记录。我发现的最简单的选择就是使用

flag_modified
。您可以选择对象上的任何字段,而不是您希望 onupdate 触发器触发的实际字段(如果您考虑一下,这是有道理的)。

flag_modified(my_object, 'any_field')
© www.soinside.com 2019 - 2024. All rights reserved.