10

从具有外键的现有(SQLite)数据库开始,SQLAlchemy可以自动生成relationshipsSQLAlchemy可以自动从数据库模式创建关系吗?

SQLAlchemy类是通过__table_args__ = {'autoload': True}自动创建的。

目标是轻松访问相关表中的数据,而无需手动添加所有关系(即不使用sqlalchemy.orm.relationship()sqlalchemy.orm.backref)。

回答

9

[更新]从SQLAlchemy 0.9.1开始,有Automap extension这样做。

对于SQLAlchemy < 0.9.0可以使用sqlalchemy反射。

SQLAlchemy反射加载表之间的外键/主键关系。但不会在映射类之间创建关系。实际上反射不会为你创建映射类 - 你必须指定映射类名。

其实我认为反射支持加载外键是一个很好的帮手和省时的工具。使用它,您可以使用连接构建查询,而无需指定用于连接的列。

from sqlalchemy import * 
from sqlalchemy import create_engine, orm 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import relationship 



metadata = MetaData() 
Base = declarative_base() 
Base.metadata = metadata 

db = create_engine('<db connection URL>',echo=False) 
metadata.reflect(bind=db) 

cause_code_table = metadata.tables['cause_code'] 
ndticket_table = metadata.tables['ndticket'] 

sm = orm.sessionmaker(bind=db, autoflush=True, autocommit=True, expire_on_commit=True) 
session = orm.scoped_session(sm) 

q = session.query(ndticket_table,cause_code_table).join(cause_code_table) 
for r in q.limit(10): 
    print r 

而且当我使用反射来运行查询现有的数据库 - 我只定义映射类名,表绑定关系,但没有必要定义这些关系表列。

class CauseCode(Base): 
    __tablename__ = "cause_code" 

class NDTicket(Base): 
    __tablename__ = "ndticket" 
    cause_code = relationship("CauseCode", backref = "ndticket") 


q = session.query(NDTicket) 
for r in q.limit(10): 
    print r.ticket_id, r.cause_code.cause_code 

总体SQLAlchemy的反射已经是功能强大的工具,节省了我的时间,所以手动添加关系对我来说是小的开销。

如果我将不得不开发使用现有外键在映射对象之间添加关系的功能,我将从使用reflection with inspector开始。使用get_foreign_keys()方法提供了建立关系所需的所有信息 - 在目标表中引用表名,引用的列名和列名。并将使用此信息将关系添加到映射类中。

insp = reflection.Inspector.from_engine(db) 
print insp.get_table_names() 
print insp.get_foreign_keys(NDTicket.__tablename__) 
>>>[{'referred_table': u'cause_code', 'referred_columns': [u'cause_code'], 'referred_schema': None, 'name': u'SYS_C00135367', 'constrained_columns': [u'cause_code_id']}] 
相关问题