使用SQLAlchemy创建非持久对象:关系中错误使用backref?

1 投票
1 回答
716 浏览
提问于 2025-04-17 16:01

我想创建一些名为 Task 的对象,并用 SQLAlchemy 把其中一些存储到数据库里,而把其他的丢掉。目前这个类是这样创建的:

Base = declarative_base()

class Task(Base):
    __tablename__ = 'tasks'
    id = Column(Integer, primary_key=True)
    hostID = Column(Integer, ForeignKey('hosts.id'))
    name = Column(String)
    host = relationship("Host", backref="tasks", cascade_backrefs=False)

def __init__(self, host, name):
    self.host = host
    self.name = name


class Host(Base):
    __tablename__ = 'hosts'
    id = Column(Integer, primary_key=True)
    hostname = Column(String)

当我执行

newTask1= GridTask(myHost, myName)
Session.add(newTask1)
Session.commit()

newTask2= GridTask(myHost, otherName)
Session.commit()

第一个任务在第一次提交时被存储,这没问题;但是第二个任务在第二次提交时被存储,这正是我想避免的。

我的问题是,如何声明 Task 和 Host 类,以便只有在明确要求时,某个实例才会被保存到数据库中?我是不是正确使用了 "cascade_backrefs"?

谢谢你的帮助。

1 个回答

1

其实是反过来的(别担心,我自己也不知道该用哪个方向,直到我试了一个简单的测试):

class Task(Base):
    __tablename__ = 'tasks'
    id = Column(Integer, primary_key=True)
    hostID = Column(Integer, ForeignKey('hosts.id'))
    name = Column(String)
    host = relationship("Host", backref=backref("tasks", cascade_backrefs=False))

    def __init__(self, host, name):
        self.host = host
        self.name = name

这是因为机制是这样的:

  1. 新建一个任务
  2. 把任务的主机设置为某个主机
  3. 反向引用生效,等于说把这个任务加到某个主机的任务列表里
  4. 正是第3步让“任务”成为“主机”的子任务,所以它被连带进来了
  5. 在任务上设置cascade_backrefs=False意味着,“如果这个事件是从反向引用开始的(在这个上下文中‘主机’就是反向引用),就不要执行保存-更新的连锁反应。”

撰写回答