Python inheritance in sqlalchemy

So I'm new to this python and sqlalchemy. I need help with inheritance or maybe mixin (but rather inheritance).

I have psudo code, but I have not made any progress:

Base = declarative_base() class ModelBase(Base): """Base model that only defines last_updated""" __tablename__ = 'doesnotexistandtheclassshouldnotbeinstantiated' #all tables inheriting from ModelBase will have this column last_updated = Column(DateTime) def __init__(self, last_updated): self.last_updated = last_updated class User(ModelBase): """Defines the user but should also have the last_updated inherited from ModelBase""" __tablename__ = 'user' id = Column(Integer, primary_key=True) def __init__(self, ....): ModelBase.__init__(last_updated) 

I want all tables inheriting from ModelBase to also have last_updated. How can I do it?

UPDATED CODE:

 class BaseUserMixin(object): """Base mixin for models using stamped data""" @declared_attr def last_updated(cls): return Column(DateTime) @declared_attr def last_updated_by(cls): return Column(String) def __init__(self, last_updated, last_updated_by): self.last_updated = last_updated self.last_updated_by = last_updated_by Base = declarative_base(cls=BaseUserMixin) class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True) name = Column(String) email = Column(String) fullname = Column(String) password = Column(String) enabled = Column(Boolean) def __init__(self, name, fullname, password, email, last_updated, last_updated_by): self.name = name self.fullname = fullname self.password = password self.email = email # goes wrong here super(User, self).__init__(last_updated, last_updated_by) def __repr__(self): return "<User('%', '%', '%', '%', '%', '%')>"\ % (self.name, self.fullname, self.password, self.email, self.last_updated, self.last_updated_by ) 

Error:

 _declarative_constructor() takes exactly 1 argument (3 given) 

What could be the problem? I thought it was working, but when the debugger was restarted, this failed.

+4
source share
1 answer

Solution declared_attr ; which will be called and added to DeclarativeMeta instances at any time:

Edit : __init__ , automatically provided by declarative , cannot call super() . if you want it, it should be the last one, and the only way to do this is to use the usual mixin.

 import datetime from sqlalchemy import Column, DateTime, Integer, String from sqlalchemy.ext.declarative import declared_attr, declarative_base class BaseMixin(object): @declared_attr def last_updated(cls): return Column(DateTime) def __init__(self, last_updated, *args, **kwargs): super(BaseMixin, self).__init__(last_updated=datetime.datetime.now(), *args, **kwargs) print "BaseMixin.__init__" self.last_updated = last_updated ModelBase = declarative_base() 

Please note that mixin should be the first!

 class User(BaseMixin, ModelBase): """Defines the user but should also have the last_updated inherited from ModelBase""" __tablename__ = 'user' id = Column(Integer, primary_key=True) username = Column(String) def __init__(self, *args, **kwargs): super(User, self).__init__(last_updated=datetime.datetime.now(), *args, **kwargs) print "User.__init__" if __name__ == '__main__': from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine('sqlite:///:memory:', echo=True) ModelBase.metadata.create_all(engine) user = User(username='alice') Session = sessionmaker(engine) session = Session() session.add(user) session.commit() 

Nonetheless; Are you sure you want to use __init__ for this first? __init__ not called when objects are returned from requests; and you really want the column to change right now when it has changed. This is already baked in Column() :

 from sqlalchemy import func class BaseMixin(object): @declared_attr def created_date(cls): return Column(DateTime, default=func.now()) @declared_attr def modified_date(cls): return Column(DateTime, default=func.now(), onupdate=func.now()) 

back to using cls= argument

 ModelBase = declarative_base(cls=BaseMixin) class User(ModelBase): __tablename__ = 'user' id = Column(Integer, primary_key=True) username = Column(String) if __name__ == '__main__': engine = create_engine('sqlite:///:memory:', echo=True) ModelBase.metadata.create_all(engine) user = User(username='alice') Session = sessionmaker(engine) session = Session() session.add(user) session.commit() session = Session() sameuser = session.query(User).one() sameuser.username = 'bob' session.commit() 
+6
source

All Articles