SQLAlchemy - 在另一个实例的__init__中创建实例

1 投票
1 回答
4646 浏览
提问于 2025-04-17 07:08

我刚接触SQLAlchemy(所以我的术语可能不太准确)。我想在一个对象的构造函数里创建另一个数据库对象,但问题是我无法把这个对象添加到会话中,所以出现了错误。

我的数据库结构大概是这样的:

class Tag(Base):
    __tablename__ = 'tag'

    id = Column(Integer, Sequence('tag_id_seq'), primary_key=True, nullable=False)
    type = Column(String(1), nullable=False)
    name = Column(String(255), unique=True, nullable=False)

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

    def __repr__(self):
        return "<Tag('%s')>" % (self.id)


class Venue:
    __tablename__ = 'venue'

    tag_id = Column(Integer)
    tag_type = Column(String(1), nullable=False)
    location = Column(String(255), nullable=False)

    tag = ForeignKeyConstraint(
            (tag_id, tag_type),
            (Tag.id, Tag.type),
            onupdate='RESTRICT',
            ondelete='RESTRICT',
            )

    def __init__(self,name,location):
        self.tag = Tag('V',name)
        self.location = location

当我这样做时:

session.add(Venue("Santa's Cafe","South Pole"))

我得到了一个错误:

UnmappedInstanceError: Class '__builtin__.instance' is not mapped

我猜这是因为在Venue的构造函数里创建的Tag对象没有被添加到会话中。我的问题是,我应该如何以及何时去做这个操作。(如果可以的话,我真的希望能在构造函数里创建这个Tag对象)。我觉得我可以用scoped_session来解决这个问题,但那似乎不是个好办法。

谢谢

1 个回答

2
  1. 要让Venue能够正常工作,得让它继承自Base。否则Venue就无法被正确映射。
  2. ForeignKeyConstraint移动到__table_args__里去。
  3. 把现在没有意义的tag属性替换成和Tagrelationshiprelationshipcascade参数默认值是'save-update',这会把新添加的对象放到和父对象同一个会话里。

来自文档:

save-update - 这个选项会把Session.add()操作进行级联。也就是说,无论是未来还是过去对add()的调用,新添加到集合或单一关系中的项目都会被放到和父对象同一个会话里。同时,这也适用于那些已经从这个关系中移除但仍然在未刷新历史中的项目。

撰写回答