繁体   English   中英

SQLAlchemy - 设置关系时更新ForeignKey

[英]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_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

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

首先,下面的所有示例都假设您的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM