我有一个班级:
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_id
和element2_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
我该如何解决这个问题?处理这种情况的最佳方法是什么?
答案 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
等典型默认值,它通常会执行“正确的操作”,并确保在需要时准备好属性。