Ronnie
Ronnie

Reputation: 391

How to resolve sqlalchemy.orm.exc.UnmappedInstanceError

I'm using Python Sqlalchemy for MYSQL db. I wrote the following script to create the class object and then add a row in the table.

from sqlalchemy import create_engine, MetaData, Table, Column, ForeignKey
from sqlalchemy.dialects.mysql.base import VARCHAR, LONGTEXT, INTEGER
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine("mysql+mysqldb://root:@localhost/mydb")
connection = engine.connect()

Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base()
metadata = MetaData()

class User(Base):
    __tablename__ = 'User'
    __abstract__ = True
    id = Column('id', INTEGER(display_width=11), primary_key=True, nullable=False)
    email = Column('email', VARCHAR(charset='utf8mb4', collation='utf8mb4_0900_ai_ci', length=100), unique=True)
    password = Column('password', VARCHAR(charset='utf8mb4', collation='utf8mb4_0900_ai_ci', length=45))
    name = Column('name', VARCHAR(charset='utf8mb4', collation='utf8mb4_0900_ai_ci', length=100))

Base.metadata.create_all(engine)

add_user = User(email = "[email protected]",
            password = 'testing',
            name = 'testing')
session.add(add_user)
session.commit()

When I try to add to session, it throws the following errors:

 AttributeError: 'User' object has no attribute '_sa_instance_state'

 During handling of the above exception, another exception occurred:

 raise exc.UnmappedInstanceError(instance)
 sqlalchemy.orm.exc.UnmappedInstanceError: Class '__main__.User' is not mapped

I'm new to SQLalchemy as well as OOP so can't figure out what I'm doing wrong here. Any help would be appreciated

Upvotes: 3

Views: 14764

Answers (1)

SuperShoot
SuperShoot

Reputation: 10872

The problem stems from defining __abstract__ == True on User.

From the docs:

__abstract__ causes declarative to skip the production of a table or mapper for the class entirely. A class can be added within a hierarchy in the same way as mixin (see Mixin and Custom Base Classes), allowing subclasses to extend just from the special class

If you make User abstract, to get mapped, it needs to be subclassed by another model, e.g. this works:

class User(Base):
    __tablename__ = 'User'
    __abstract__ = True
    id = Column('id', INTEGER(display_width=11), primary_key=True, nullable=False)
    email = Column('email', VARCHAR(charset='utf8mb4', collation='utf8mb4_0900_ai_ci', length=100), unique=True)
    password = Column('password', VARCHAR(charset='utf8mb4', collation='utf8mb4_0900_ai_ci', length=45))
    name = Column('name', VARCHAR(charset='utf8mb4', collation='utf8mb4_0900_ai_ci', length=100))

class AUser(User):
    pass

if __name__ == '__main__':
    Base.metadata.create_all(bind=engine)

    add_user = AUser(email = "[email protected]",
                password = 'testing',
                name = 'testing')
    session.add(add_user)
    session.commit()

Upvotes: 3

Related Questions