Python 在SQLAlchemy中修改另一个字段时如何更新关系

Python 在SQLAlchemy中修改另一个字段时如何更新关系,python,sqlalchemy,Python,Sqlalchemy,我在SQLAlchemy中有一个简单的客户机模型,主要使用声明式。此模型有一个名称字段,并且与元音码模型有多对多关系。代码如下所示: class MetaphoneCode(Base): """Represents a metaphone code """ __tablename__ = 'mcodes' id = Column(Integer, Sequence('mcodes_seq_id'), primary_key=True) code = Col

我在SQLAlchemy中有一个简单的
客户机
模型,主要使用声明式。此模型有一个
名称
字段,并且与
元音码
模型有多对多关系。代码如下所示:

class MetaphoneCode(Base):
    """Represents a metaphone code
    """
    __tablename__ = 'mcodes'
    id = Column(Integer, Sequence('mcodes_seq_id'), primary_key=True)
    code = Column(String(20), index=True, nullable=False)


client_mcode_assoc_table = Table(
    'client_mcodes',
    Base.metadata,
    Column('client_id', ForeignKey('clients.id')),
    Column('mcode_id', ForeignKey('mcodes.id')))


class Client(Base):
    __tablename__ = 'clients'
    id = Column(Integer, Sequence('client_id_seq'), primary_key=True)
    name = Column(Unicode(100), index=True)
    mcodes = relationship('MetaphoneCode', secondary=client_mcode_assoc_table)
现在,由于变音代码必须在
名称
本身发生变化时发生变化,因此我想表达这一需求,以便在我进行
client.name=“John Doe”
时,我想计算与这些名称(名字和姓氏)相关的变音代码,并更新
mcodes
关系


更新:我找到了一个引用的简单解决方案;所以我的问题最好表述为“ORM属性事件系统是更新属性以响应另一个属性更改的最佳实践机制吗?”

也许使用getter和setter可以解决您的问题

SqlAlchemy提供了一种将getter和setter添加到模型属性的方法。我自己从来没用过。看


然而,我不知道在这些setter中运行业务逻辑代码是否是好的实践。也许更有经验的人会告诉我们。

我通过使用事件成功地做到了这一点:

@event.listens_for(Client.name, 'set')
def update_mcodes(target, value, oldvalue, initiator):
    target.recalculate_mcodes(value)

不过,这是推荐的方法吗?我将阅读@Xaqq建议的混合方法,并决定这是否比
事件
更好。

为什么您不想通过InstrumentedAttribute?@ScotchAndSoda我不想避免InstrumentedAttribute,只是我将创建一个子类,在它的
\uuuuuuu集
方法上调用一些回调。但这并不是真的需要,因为SQLAlchemy已经有了
@event.listens\u的
,这与我通过破解InstrumentedAttribute实现的几乎相同。@Xaqq,@ScotchAndSoda:我真的看不出混合属性如何匹配我的用例。似乎我必须用setter定义一个
fullname
@hybrid\u属性。但是,我必须更改所有代码以设置
fullname
,而不是
name
。或者我必须将列
name
更改为例如
\u name
,然后将
name
定义为混合属性。这两种方法似乎都不正确。@manu我想第二种方法是使用hybrid property的方法(据我所知),我已经广泛阅读了Hybrids文档。我认为它适用于其他用例。那我就标记我的答案。但是我已经在我的代码中使用了混合属性用于其他目的,所以感谢指针。我不知道事件,可能比混合属性更好。当然,如果有经验的用户给我们提供infos:D,那就太好了