Это заняло у меня некоторое время, но я понял, как использовать SQLAlchemy для моделирования отношений между двумя различными типами баз данных:
Base = declarative_base()
class Survey(Base):
__tablename__ = 'SURVEY'
survey_id = Column("SURVEY_ID", Integer, primary_key=True)
term_id = Column("TERM_ID", Integer, nullable=False)
# Because the TERM table is in Oracle, but the SURVEY table is in
# MySQL, I can't rely on SQLAlchemy's ForeignKey. Thus,
# I need to specify the relationship entirely by hand, like so:
term = relationship("Term",
primaryjoin="Term.term_id==Survey.term_id",
foreign_keys=[term_id],
backref="surveys"
)
class Term(Base):
__tablename__ = 'TERM'
term_id = Column(Integer, primary_key=True)
term_name = Column(String(30))
start_date = Column(Date)
end_date = Column(Date)
mysql_engine = create_engine(MYSQL)
oracle_engine = create_engine(ORACLE)
Session = scoped_session(sessionmaker(
binds={
Term: oracle_engine,
Survey: mysql_engine
}
))
if __name__ == "__main__":
survey = Session.query(Survey).filter_by(survey_id=8).one()
print survey.term
print survey.term.surveys
Я должен сделать это, потому что таблица TERM находится в базе данных Oracle, к которой у меня есть только права на чтение, и я пишу приложение, которое записывает опросы, проведенные студентами, по этому термину.
Вышеописанное работает, но оно очень хрупкое, когда количество таблиц возрастает, так как Session должен точно указать, какие сопоставленные классы соответствуют какому движку. Мне бы очень хотелось иметь возможность использовать другой Base
для определения того, какие таблицы принадлежат какому-либо механизму, вместо того, чтобы связывать каждую таблицу по отдельности. Как это:
mysql_engine = create_engine(MYSQL)
oracle_engine = create_engine(ORACLE)
MySQLBase = declarative_base(bind=mysql_engine)
OracleBase = declarative_base(bind=oracle_engine)
class Survey(MySQLBase):
__tablename__ = 'SURVEY'
survey_id = Column("SURVEY_ID", Integer, primary_key=True)
term_id = Column("TERM_ID", Integer, nullable=False)
class Term(OracleBase):
__tablename__ = 'ads_term_v'
term_id = Column(Integer, primary_key=True)
term_name = Column(String(30))
start_date = Column(Date)
end_date = Column(Date)
Survey.term = relationship("Term",
primaryjoin="Term.term_id==Survey.term_id",
foreign_keys=[Survey.term_id],
backref="surveys"
)
Session = scoped_session(sessionmaker())
if __name__ == "__main__":
survey = Session.query(Survey).filter_by(survey_id=8).one()
print survey.term
print survey.term.surveys
К сожалению, это приводит к следующей ошибке при выполнении запроса:
sqlalchemy.exc.InvalidRequestError: When initializing mapper Mapper|Survey|SURVEY, expression 'Term.term_id==Survey.term_id' failed to locate a name ("name 'Term' is not defined"). If this is a class name, consider adding this relationship() to the <class '__main__.Survey'> class after both dependent classes have been defined.
, хотя я добавил и добавил отношение () к опросу после определения термина.
У кого-нибудь есть предложения?