[英]SQLAlchemy - Update ForeignKey when setting the relationship
我有一节课:
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
我怎么解决这个问题? 处理这种情况的最佳方法是什么?
首先,下面的所有示例都假设您的ExampleClass
实例至少处于挂起状态(如果不是“持久”状态(即session.add(a)
)。 换句话说,如果您还没有与Session
交互并且没有将ExampleClass
对象添加到一个,那么您将不会获得relationship()
任何数据库级行为,其中维护外键列值是主要特征。 您当然可以直接自由地完成此任务:
a = ExampleClass(element_id=element_obj.id)
但这显然没有利用relationship()
构造提供的自动化。
通过relationship()
分配外键属性发生在刷新期间,这是一个仅在需要与数据库交互时才发生的过程,例如在使用session.query()
发出SQL语句之前或完成事务之前使用session.commit()
。
通常, relationship()
的哲学是你在这里只处理“元素”和“元素2”属性,并在后台处理外键属性。 您可以像这样编写查询:
session.query(ExampleClass).\
filter_by(element=self.element).\
filter_by(element2=element2)
ORM将进行比较,例如SomeClass.somerelationship=someobject
并将其转换为外键表达式SomeClass.some_fk=some_id
,但不同的是,“some_id”的最终值的评估被推迟到右边的那个之前查询已执行。 在执行查询之前, Query()
对象告诉Session
“autoflush”,这将导致您插入ExampleClass
行,并将element_obj
的主键标识符分配给ExampleClass
对象上的element_id
属性。
你可以在使用像这样的FK属性时获得类似的效果,这主要是为了理解它是如何工作的:
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
这样的外键属性,那么你也需要明确地做一些relationship()
为你做的事情。 如果严格处理对象实例和relationship()
- autoflush
属性,并保留启用autoflush
等典型默认值,它通常会执行“正确的操作”,并确保在需要时准备好属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.