【问题标题】:Is it possible to declare relationship after class is created by automap in SqlAlchemy在SqlAlchemy中通过automap创建类后是否可以声明关系
【发布时间】:2014-11-15 06:39:32
【问题描述】:

我是 sqlalchemy 的新手。我已按照教程创建与 mysql 数据库有关系的现有数据库的自动映射

from sqlalchemy import create_engine, MetaData, Column, Table, ForeignKey
from sqlalchemy.ext.automap import automap_base, generate_relationship
from sqlalchemy.orm import relationship, backref
from config import constr, mytables

def _gen_relationship(base, direction, return_fn,
                  attrname, local_cls, refferred_cls, **kw):
    return generate_relationship(base, direction, return_fn, attrname, local_cls, refferred_cls, **kw)

engine = create_engine(constr)
metadata = MetaData()
metadata.reflect(engine, only=mytables)
Base = automap_base(metadata=metadata)
Base.prepare(engine, reflect=True, generate_relationship=_gen_relationship)
Tableclass1 = Base.classes.table1
Tableclass2 = Base.classes.table2

Table2.ID 映射到table1 的列之一。但是当我尝试使用查询并加入table1table2 时,它报告错误说“找不到任何外键关系”。既然我知道这两个表的关系,我有没有办法在创建类实例后声明这种关系?或者有没有办法在查询函数中明确地告诉这种关系? 谢谢!

【问题讨论】:

    标签: python mysql sqlalchemy relationship automap


    【解决方案1】:

    虽然可以在@mpolednik 提到的查询中执行此操作,但如果我正确阅读了您的问题,理想的解决方案是在您的类中声明关系以供重复使用。

    可以简单地通过预先声明您希望使用的类来实现,如下所示:

    from sqlalchemy.ext.automap import automap_base
    from sqlalchemy.orm import Session, relationship
    from sqlalchemy import create_engine, Column, String
    
    Base = automap_base()
    
    engine = create_engine("postgresql://user:pass@localhost:5432/mydb")
    
    # pre-declare User for the 'user' table
    class User(Base):
        __tablename__ = 'user'
    
        # override schema elements like Columns
        oname = Column('originalname', String)
    
        # and a relationship. I name it 'weird' because in my database schema
        # this relationship makes absolutely no sense, but it does demonstrate
        # the point
        weird = relationship("usergroup",
                             foreign_keys='usergroup.id',
                             primaryjoin='and_(usergroup.id==User.id)')
    
    Base.prepare(engine, reflect=True)
    session = Session(engine)
    
    # Test this by querying the User table and then following the relationship
    u = session.query(User).filter(User.oname == 'testuser').one()
    print (u.oname)
    for g in u1.weird:
        print g.name
    

    请参阅此处查看文档(包括另一个示例):http://docs.sqlalchemy.org/en/latest/orm/extensions/automap.html?highlight=automap#specifying-classes-explicitly

    【讨论】:

      【解决方案2】:

      您可以通过使用连接 SQLAlchemy 的 join 方法的 onclause 参数来明确地做到这一点。 onclause 参数的使用与 SQL 的 JOIN 类似,例如

      sqlalchemy.orm.join(table1, table2, onclause=table2.ID == table1.your_attribute)
      

      您还可以通过简单地在类中声明外键来声明绕过数据库中外键的存在:

      Column('ID', Integer, ForeighKey('table1.your_attribute'))
      

      【讨论】:

        猜你喜欢
        • 2011-07-08
        • 2010-12-19
        • 2020-03-31
        • 2018-11-24
        • 2020-11-18
        • 1970-01-01
        • 1970-01-01
        • 2011-06-30
        • 2019-11-10
        相关资源
        最近更新 更多