SQLAlchemy - 设置关系时更新ForeignKey

时间:2012-12-25 05:09:17

标签: python sqlalchemy

我有一个班级:

class ExampleClass(Base):
    __tablename__ = 'chart'
    id = Column(Integer, primary_key=True)
    element_id = Column(Integer, ForeignKey('anotherTable.id'))
    element = relationship(AnotherClass)
    element2_id = Column(Integer, ForeignKey('anotherTable2.id'))
    element2 = relationship(AnotherClass2)

我想根据element_idelement2_id

进行查找
class ExampleClass(Base):
    ...
    def get_with_element2(self, element2):
        return session.query(ExampleClass).\
                       filter_by(element_id = self.element_id,
                                 element2_id = element2.id).first()

我发现的问题是,如果我实例化一个新的ExampleClass对象并为其分配element,则element_id字段未设置:

a = ExampleClass(element=element_obj)
a.element_id => None

我该如何解决这个问题?处理这种情况的最佳方法是什么?

1 个答案:

答案 0 :(得分:10)

首先,以下所有示例都假设您的ExampleClass实例至少处于pending状态,如果不是“持久”状态(即session.add(a))。换句话说,如果您尚未与Session交互并且尚未将ExampleClass对象添加到一个,那么您将无法获得{{1}的任何数据库级行为其中维护外键列值是主要功能。您当然可以直接自由地完成这项任务:

relationship()

但显然没有利用a = ExampleClass(element_id=element_obj.id) 构造提供的自动化。

relationship()期间的外键属性分配发生在flush期间,这是一个仅在需要与数据库交互时才发生的过程,例如在使用{{发出SQL语句之前1}}或在您使用relationship()完成交易之前。

通常,session.query()的哲学是你在这里只处理“element”和“element2”属性,并在后台处理外键属性。您可以这样编写查询:

session.commit()

ORM将进行比较,例如relationship()并将其转换为外键表达式session.query(ExampleClass).\ filter_by(element=self.element).\ filter_by(element2=element2) ,但区别在于,“some_id”的最终值的评估是延迟直到执行查询之前的权利。在执行查询之前,SomeClass.somerelationship=someobject对象告诉SomeClass.some_fk=some_id“autoflush”,这将导致Query()行的插入以及主键标识符{{1被分配到Session对象的ExampleClass属性。

你仍然可以在使用像这样的FK属性时获得类似的效果,这主要是为了理解它是如何工作的:

element_obj

或者甚至更明确,先进行冲洗:

element_id

因此,在某种程度上,您希望明确地引用ExampleClass等外键属性,您还需要明确地执行session.query(ExampleClass).\ filter_by(element_id=bindparam(callable_=lambda: self.element_id)).\ filter_by(element2_id=element2.id) 为您做的事情。如果严格处理对象实例和session.flush() session.query(ExampleClass).\ filter_by(element_id=self.element_id).\ filter_by(element2_id=element2.id) 绑定属性,并保留启用element_id等典型默认值,它通常会执行“正确的操作”,并确保在需要时准备好属性。