【问题标题】:How to automatically reflect table relationships in SQLAlchemy or SqlSoup ORM?如何在 SQLAlchemy 或 SqlSoup ORM 中自动反映表关系?
【发布时间】:2011-10-10 06:56:20
【问题描述】:
如何告诉 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)
【问题讨论】:
标签:
sql
orm
foreign-keys
sqlalchemy
sqlsoup
【解决方案1】:
试试这个魔法)
适用于简单的 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()