Как автоматически отразить табличные отношения в SQLAlchemy или SqlSoup ORM? - PullRequest
6 голосов
/ 21 июля 2011

Как мне указать SQLAlchemy автоматически отражать базовые ссылки на внешние ключи как ссылки на другие объекты ORM, а не целочисленные поля?

В обоих SQLAlchemy , и это SqlSoup столбцы таблицы отражаются автоматически, и отношения могут быть определены вручную:

class User(Base):
    __table__ = metadata.tables['users']
    loan = relation(Loans)

...

You can define relationships on SqlSoup classes:
>>> db.users.relate('loans', db.loans)

1 Ответ

0 голосов
/ 31 октября 2012

попробуй эту магию) Работает для простых отношений FK и без схем БД

from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import mapper, relation

engine = create_engine("sqlite://", echo=True)

engine.execute('''
    create table foo (
        id integer not null primary key,
        x integer
    )''')

engine.execute('''
    create table bar (
        id integer not null primary key,
        foo_id integer,
        FOREIGN KEY(foo_id) REFERENCES foo(id)
    )''')

metadata = MetaData()
metadata.reflect(bind=engine)


MAPPERS = {
}

repr_name = lambda t: '%s%s' % (t[0].upper(), t[1:])

for table in metadata.tables:

    cls = None
    # 1. create class object
    cls_name = repr_name(str(table))
    exec("""class %s(object): pass""" % cls_name)
    exec("""cls = %s""" % cls_name)

    # 2. collect relations by FK
    properties = {}
    for c in metadata.tables[table].columns:
        for fk in c.foreign_keys:
            name = str(fk.column).split('.')[0]
            properties.update({
                name: relation(lambda: MAPPERS[repr_name(name)]),
            })

    # 3. map table to class object 
    mapper(cls, metadata.tables[table], properties=properties)


    MAPPERS.update({cls_name: cls})

if __name__ == '__main__':
    from sqlalchemy.orm import sessionmaker

    print 'Mappers: '
    for m in MAPPERS.values():
        print m

    session = sessionmaker(bind=engine)()

    foo = Foo()
    foo.x = 1
    session.add(foo)

    session.commit()

    print session.query(Foo).all()

    bar = Bar()
    bar.foo = foo
    session.add(bar)
    session.commit()

    print session.query(Bar).all()
...