简体   繁体   中英

SQLAlchemy Bidirectional Association Proxy

I'm trying to create a simple many to many relationship with a mapping table containing metadata about the relationship it represents with association proxies on both ends using SQLAlchemy. However, I can't seem to get it to work. Here's the toy example I've been working with to try to figure it out:

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)

I added the creator functions so I could avoid writing an __init__ that won't work for my actual use case (takes single argument), and included the creation of the FooBar in each because I read in some of the documentation that the item being appended needs to already have a linking table instance associated with it. I'm sure I'm just missing something obvious (or maybe even trying to do something that just can't be done), but after much digging through the docs and Googling, I can't figure out why it doesn't work. What am I doing wrong?

Your problem lies in the creator : It should return the new instance of FooBar and not bar or foo :

def bar_creator(value):
    return FooBar(bar=value)

And analogous for foo_creator .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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