Reputation: 391
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
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