无法在SQLAlchemy中映射多对多关系

时间:2018-02-04 19:22:21

标签: python orm sqlalchemy

我有两个对象,用户会议室,这两个对象都继承自基础对象。

class BaseModel:
    __metaclass__ = Serializable

    created = Column(DateTime, default=func.now())
    modified = Column(DateTime, default=func.now(), onupdate=func.now())

    @declared_attr
    def __tablename__(self):
        return self.__name__.lower()


Base = declarative_base(cls=BaseModel)

这是我的用户模型,其中包含与会议室顶层声明的多对多关联。

association_table = Table('users_rooms', Base.metadata,
    Column('user_id', Integer, ForeignKey('user.id')),
    Column('room_id', Integer, ForeignKey('room.id'))
)
class User(Base):
    __table_args__ = {'extend_existing': True}

    id = Column(Integer, primary_key=True)
    mobile = Column(String(20), index=True, unique=True)
    rooms = relationship("Room", secondary=association_table, 
    back_populates="users")

这是 Room 模型。

association_table = Table('users_rooms', Base.metadata,
                          Column('user_id', Integer, ForeignKey('user.id')),
                          Column('room_id', Integer, ForeignKey('room.id'))
                          )


class Room(Base):

    __table_args__ = {'extend_existing': True}

    id = Column(Integer, primary_key=True)
    room_type = Column(String(50), default=RoomType.PRIVATE)
    hex_code = Column(String(100), unique=True)
     users = relationship("User", secondary=association_table, back_populates="rooms")

当我尝试编译时,我收到以下错误。

sqlalchemy.exc.InvalidRequestError: Table 'users_rooms' is already defined for this MetaData instance.  Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

1 个答案:

答案 0 :(得分:1)

该错误试图告诉您,您不需要 - 也不应该 - 在两个模块中定义关联表。在其中一个或自己的模块中定义它,然后导入它,或者使用relationship()secondary="users_rooms"中懒惰地引用它:

# Room model. Note the absence of `association_table`

class Room(Base):

    id = Column(Integer, primary_key=True)
    room_type = Column(String(50), default=RoomType.PRIVATE)
    hex_code = Column(String(100), unique=True)
    users = relationship("User", secondary="users_rooms", back_populates="rooms")

从与MetaData模型关联的Room集合中查找作为secondary=中传递的字符串值的表名。

你也不需要撒

__table_args__ = {'extend_existing': True}

在你的模特中。如果在没有它的情况下遇到与此问题中的错误类似的错误,则表格已经创建并包含在MetaData集合中,然后才能构建模型。例如,您可能使用了反射。