Radissan
Radissan

Reputation: 21

SQLAlchemy can't reflect table with primary key

These are the classes:

class User(db.Model):
    __tablename__ = 'Users'
    UserID = db.Column(
        db.Integer,
        primary_key=True,
        autoincrement=True,
        nullable=False
    )
    FirstName = db.Column(db.String(255), nullable=False)
    LastName = db.Column(db.String(255), nullable=False)
    Username = db.Column(db.String(255), nullable=False)
    Password = db.Column(db.String(255), nullable=False)

class UserType(db.Model):
    __tablename__ = 'UserTypes'
    TypeID = db.Column(
        db.Integer,
        primary_key=True,
        autoincrement=True,
        nullable=False
    )
    Type = db.Column(db.String(255), nullable=False)

    __table_args__ = (
        db.CheckConstraint(
            "Type IN ('Role1', 'Role2', 'Role3')"
        ),
    )


class UserPrivilege(db.Model):
    __tablename__ = 'UserPrivileges'
    UserID = db.Column(db.Integer, primary_key=True)
    UserTypeID = db.Column(db.Integer, primary_key=True)

    __table_args__ = (
        db.ForeignKeyConstraint(
            ['UserID'],
            ['Users.UserID'],
        ),
        db.ForeignKeyConstraint(
            ['UserTypeID'],
            ['UserTypes.TypeID'],
        ),
    )

    PrivilegeUserInfoBackref = db.relationship(
        'User',
        backref='PrivilegeUserInfoBackref',
        lazy=True,
    )
    PrivilegeUserTypeInfoBackref = db.relationship(
        'UserType',
        backref='PrivilegeUserTypeInfoBackref',
        lazy=True,
    )

And here is the code for reflecting the tables:

Base = automap_base()
engine = sa.create_engine(
    DATABASE_CONNECTION,
    convert_unicode=True,
    pool_size=10,
    max_overflow=20
)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base.prepare(engine, reflect=True)

The 'Users' and 'UserTypes' classes appear in Base.classes._data but for some reasson 'UserPrivileges' does not appear in Base.classes._data. All I managed to find is that tables with no primary key can't be reflected but as you can see that is not the case here. I also have some more tables that have composite primary key with backrefs but that are reflected with no problem.

So, can anyone give me any suggestions in order to reflect the last table as well, please ?

Upvotes: 0

Views: 657

Answers (1)

Ilja Everilä
Ilja Everilä

Reputation: 52929

The table created for UserPrivilege ticks all the boxes of a many-to-many relationship's "secondary" table, and as such is not mapped directly when using the automap extension. This behaviour is also explained in the note of "Basic Use":

By viable, we mean that for a table to be mapped, it must specify a primary key. Additionally, if the table is detected as being a pure association table between two other tables, it will not be directly mapped and will instead be configured as a many-to-many table between the mappings for the two referring tables.

Your table should exist as Base.metadata.tables['UserPrivileges'].

Upvotes: 1

Related Questions