为什么SQLAlchemy中的ForeignKey和RelationshipProperty属性不会自动同步?

时间:2014-07-10 20:35:35

标签: python sqlalchemy foreign-key-relationship

我试图找出SQLAlchemy处理外键的方式。

考虑这些模型:

class ModelOne(Base):
   __tablename__ = 'model_one'

   id = Column(Integer, primary_key=True)
   ...

class ModelTwo(Base):
   __tablename__ = 'model_two'

   id = Column(Integer, primary_key=True)
   one_id = Column(Integer, ForeignKey('model_one.id'))
   one = relationship('ModelOne')

我假设如果我们有两个这样的模型,那么SQLAlchemy会发现ModelTwo.one_id和ModelTwo.one指的是同一个数据库列。

创建ModelTwo记录时,我们可以使用ModelOne记录的数字ID或ModelOne实例来填充FK字段:

one = DBSession.query(ModelOne)....
two_a = ModelTwo(one_id=one.id)
two_b = ModelTwo(one=one)

这很有效。

但是这里有一个转折:在实例化ModelTwo实例后,根据我们初始化FK字段的方式,它的一个或另一个表示将保持未填充:

two_a.one is None # evaluates to True
two_b.one_id is None # evaluates to True

这是预期的行为吗?如果是这样,这必须是开发人员头上的一个巨大的危险信号。当我们从DB检索记录作为声明性模型类的实例时,将填充record.one和record.one_id,但是当我们创建新记录时,情况并非如此!

1 个答案:

答案 0 :(得分:4)

这是标准行为。 SQLAlchemy不会在提交之前根据其他更改反映外键更改或关系更改。如果您想在设置另一个属性时设置该属性,则可以使用Attribute Set事件。

通常鼓励您使用关系并忽略外键,因为SQLAlchemy在设置关系时会在后台执行很多不错的“魔术”。如果您希望外键执行相同的魔术,请参阅Expire Relationship on FK Change食谱。

现在这只是我的观点,但这不是一个“红旗”。您应该构建程序,以避免在新实例或更新实例与持久实例之间进行比较。