当您使用不同的值更新模型的关系及其对应的列时,如何控制在提交时使用哪个值?

2024-06-26 13:36:10 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我在模型中声明了一个克隆方法,如下所示:

def clone(self):
    valid_cols = [key for key, val in vars(type(self)).items() if isinstance(val, InstrumentedAttribute) and key not in self.__table__.primary_key.columns]
    return type(self)(**{key: getattr(self, key) for key in valid_cols})

这使得克隆记录并更新其属性变得非常方便

不过有个问题。每当我更新一个已经复制了关联关系的字段时,就会出现不希望出现的行为

例如,以:

class Parent(Base):
    __tablename__ = "parent"
    id = Column(Integer, primary_key=True)


class Child(Base):
    __tablename__ = "child"
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey(Parent.id))

    parent = relationship(Parent, backref=Backref("children", uselist=True, cascade="all"))

    def clone(self):
        from sqlalchemy.orm.attributes import InstrumentedAttribute
        valid_cols = [key for key, val in vars(type(self)).items() if isinstance(val, InstrumentedAttribute) and key not in self.__table__.primary_key.columns]
        return type(self)(**{key: getattr(self, key) for key in valid_cols})


metadata.create_all()


parent1 = Parent()
parent2 = Parent()
child1 = Child(parent=parent1)

s.add_all([parent1, parent2, child1])
s.commit()

child2 = child1.clone()
child2.parent_id = parent2.id

child2.parent_id  # 2

s.add(child2)
s.commit()

child2.parent_id  # 1
child2.parent is parent1  # True

因此,很明显,child2的父母应该是parent2,而不是parent1。但是,在克隆方法期间,parent1直接设置在child2的“Child.parent”关系上,因此即使child2的“Child.parent\u id”列后来设置为parent2的id,orm也不在乎,并在提交时放弃该更新

我的问题是,当关系属性和列属性之间存在分歧时,有没有办法让orm将最后修改的属性作为绝对真理

我可以避免在clone方法中设置关系属性,但我不想这样做,因为在更复杂的情况下,访问旧对象的关系非常有用,而且我发现在我的用例中,能够直接设置列属性而不是设置它们的关系属性也很重要

在将任何内容提交到数据库之前,我还希望对克隆对象执行任何必需的更新

基本上,有没有简单的银弹?我是否可以修改clone方法,使其他所有内容保持不变,在示例代码的末尾,child2的父对象将是parent2而不是parent1

非常感谢


Tags: 方法keyinselfid属性关系clone