SQLAlchemy双向关联代理

5

我正在尝试使用SQLAlchemy在两个表之间创建一个简单的多对多关系,其中包含有关该关系的元数据的映射表,并在两端使用关联代理。但是,我似乎无法使其正常工作。以下是我一直在使用的玩具示例:

Base = declarative_base()


def bar_creator(bar):

    _ = FooBar(bar=bar)
    return bar


class Foo(Base):

    __tablename__ = 'foo'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    bars = association_proxy('bar_associations', 'bar',
                             creator=bar_creator)


def foo_creator(foo):

    _ = FooBar(foo=foo)
    return foo


class Bar(Base):

    __tablename__ = 'bar'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    foos = association_proxy('foo_associations', 'foo',
                             creator=foo_creator)


class FooBar(Base):

    __tablename__ = 'fooBar'

    foo_id = Column(Integer, ForeignKey('foo.id'), primary_key=True)
    bar_id = Column(Integer, ForeignKey('bar.id'), primary_key=True)
    bazed = Column(Boolean)
    foo = relationship(Foo, backref='bar_associations')
    bar = relationship(Bar, backref='foo_associations')


Base.metadata.create_all(engine)
make_session = sessionmaker(bind=engine)
session = make_session()
foo0 = Foo(name='foo0')
session.add(foo0)
bar0 = Bar(name='bar0')
foo0.bars.append(bar0)

我添加了“creator”函数以避免编写一个对于我的实际用例无法工作的“__init__”函数,并在每个函数中包含了“FooBar”的创建,因为我在文档中读到需要被添加的项已经与链接表实例相关联。我确定我只是错过了一些明显的东西(或者甚至可能试图做一些无法完成的事情),但是经过查阅文档和搜索,我无法弄清楚为什么它不起作用。我做错了什么?

你能解释一下具体是哪里出了问题吗?我不明白为什么你需要使用creator函数来创建关联代理。 - javex
1
无论是否有创建者,它都不能正常工作,但是创建者似乎能让它走得更远一些。当将bar0附加到foo0.bars时,我从sqlalchemy/orm/attributes.py的第1140行收到了一个关键错误,即在发出集合附加事件的回退引用时,子实现=child_state.manager[key].impl。 - Silas Ray
1个回答

2
你的问题在于 creator:它应该返回 FooBar 的新实例而不是 bar 或者 foo
def bar_creator(value):
    return FooBar(bar=value)

对于 foo_creator 同样适用。


哦,这很有道理。现在它可以工作了,谢谢。我知道这一定是某些愚蠢和显而易见的东西... - Silas Ray
Lambda可以提供一种不错的方式来避免编写这些额外的创建函数,例如:creator = lambda b: FooBar(bar=b) - djpohly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接