【问题标题】:SQLAlchemy - How to map ManyToMany using autoloaded association tablesSQLAlchemy - 如何使用自动加载的关联表映射多对多
【发布时间】:2011-11-25 15:11:42
【问题描述】:

我正在自动加载一个 MSSQL 数据库。有几个 ManyToMany 关联表。我不确定如何映射每一侧。以下是它们在 db 中的典型示例:

Table: tbUsersToGroups
PK: ID_UserToGroup
FK: User_ID
FK: Group_ID

所以我可以成功地自动加载该关联表以及下面的用户和组表,但是我尝试映射边的一切都失败了。

class UserToGroup(Base):
    __tablename__ = 'tbUsersToGroups'
    __table_args__ = {'autoload':True,'extend_existing':True,'schema':'dbo'}

class User(Base):
    __tablename__ = 'tbUsers'
    __table_args__ = {'autoload':True,'schema':'dbo'}

class Group(Base):
    __tablename__ = 'tbGoups'
    __table_args__ = {'autoload':True,'schema':'dbo'}

任何帮助都会很棒。

【问题讨论】:

    标签: many-to-many sqlalchemy


    【解决方案1】:

    您已将关联表映射到一个类。将关联对象与多对多关系结合起来是非常不寻常的,并且可能会给您带来一些痛苦。如果关联表没有任何其他感兴趣的列,您可以删除映射 并使用多对多关系:

    编辑:我错过了您正在执行每个表反射而不是完整数据库反射的事实;对于多对多,您必须告诉 sqlalchemy 该表,但不将其映射到类:

    user_to_groups_table = sqlalchemy.Table('tbUsersToGroups', Base.metadata,
                       autoload=True,
                       extend_existing=True
                       schema='dbo')
    
    class User(Base):
        __tablename__ = 'tbUsers'
        __table_args__ = {'autoload':True,'schema':'dbo'}
    
    class Group(Base):
        __tablename__ = 'tbGoups'
        __table_args__ = {'autoload':True,'schema':'dbo'}
        users = relationship(User, secondary=user_to_groups_table, backref="groups")
    

    如果关联表中有 列您希望具有面向对象的访问权限,则应使用两个一对多关系来关联三个类;或者,您还可以使用关联代理来获取方便的多对多属性,以便您偶尔只需要使用这些额外的列(并且它们具有默认值):

    from sqlalchemy.ext.associationproxy import association_proxy
    class UserToGroup(Base):
        __tablename__ = 'tbUsersToGroups'
        __table_args__ = {'autoload':True,'extend_existing':True,'schema':'dbo'}
    
    class User(Base):
        __tablename__ = 'tbUsers'
        __table_args__ = {'autoload':True,'schema':'dbo'}
        usergroups = relationship(UserToGroup, backref="user")
        groups = association_proxy("usergroups", "group")
    
    class Group(Base):
        __tablename__ = 'tbGoups'
        __table_args__ = {'autoload':True,'schema':'dbo'}
        usergroups = relationship(UserToGroup, backref="group")
        users = association_proxy("usergroups", "user")
    

    【讨论】:

    • 感谢@TokenMacGuy。当我尝试您的第一个示例时,我收到一个 InvalidRequestError 说(基本上)未定义“tbUsersToGroups”。然后我尝试定义一个自动加载的类'UserToGroup',但后来我得到一个AttributeError'UserToGroup'没有foreign_keys。但是我可以通过for f in UserToGroup().__table__.foreign_keys: f 看到外键。有什么线索吗?
    • 我不经常使用autoload 没有完整的数据库反射,所以我错过了表声明的需要;请查看我的编辑。
    • 我不能在这种情况下使用完整的数据库反射的唯一原因(除非您知道解决方法)是有两次,我必须覆盖 MSSQL TIMESTAMP 列的列定义,这是服务器生成的,这意味着 SA 无法插入。无论如何,我现在给你的编辑版本一个去。再次非常感谢
    • 你可以覆盖任何你喜欢的东西;只需为反映不佳的字段提供Column 条目,sqlalchemy 将使用您的定义来支持反映的字段;另一方面,完整的数据库反射可能很慢;所以如果你真的不方便,你就不需要使用它。
    • 真的吗?!我想我会看一下完整的反射,因为这非常痛苦。我只需要将这个 MSSQL 迁移到 MongoDB,所以我手动定义 MSSQL 端的动机非常低。
    猜你喜欢
    • 1970-01-01
    • 2011-07-04
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 2013-06-04
    相关资源
    最近更新 更多