We have a database of about 100 tables with timestamp audit columns on most,
but not all tables, and use declarative to describe the database. I am
attempting to use a metaclass to create a base class that defines the audit
columns so we can stop defining them on every class. This seems to work OK
in most cases, but when I mix classes derived from my metaclass with classes
derived from the out-of-the-box base class I get an UnmappedClassError.

I am using version 0.5.8 (we will be able to upgrade soon, but not yet), but
get the same error using a metaclass customized for 0.6.

The stripped down example below should gives the error. the interesting
thing I have seen is that when running with code for our full database, the
error does not always point at the same table and occasionally gives an
Attribute error instead of the UnmappedClassError. In this example, if you
remove the product relationship property on SubSystemModule; the error
disappears. Also, if both classes are derived from AuditBase, there is no
error.

Since we generate most of the SQLAlchemy classes directly from our data
model, we can go back to adding audit columns to every class, but we don't
really want to do that.


import datetime
from sqlalchemy import __version__ as sa_ver
from sqlalchemy import (Column, ForeignKeyConstraint, PrimaryKeyConstraint,
    create_engine, MetaData, DateTime, Integer, String)
from sqlalchemy.orm import relation, backref
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta

Base = declarative_base()
metadata = Base.metadata
class AuditMeta(DeclarativeMeta):
   def __init__(cls, classname, bases, dict_):
        dict_['ModificationTS'] = Column("ModificationDate",DateTime
                ,default=datetime.datetime.now
                ,onupdate=datetime.datetime.now)
        return DeclarativeMeta.__init__(cls, classname, bases, dict_)

AuditBase = declarative_base(metaclass=AuditMeta, metadata=metadata)

class Product(AuditBase):
    __tablename__ = 'Product'
    PID = Column(Integer)
    Name = Column(String)
    __table_args__ = (
        PrimaryKeyConstraint('PID'),
        {})

class SubSystemModule(Base):
    __tablename__ = 'SubSystemModule'
    SSMID = Column(Integer)
    PID = Column(Integer)
    Name = Column(String)
    __table_args__ = (
        PrimaryKeyConstraint('SSMID'),
        ForeignKeyConstraint(['PID'],['Product.PID']),
        {})
    product = relation('Product',
        backref=backref('subsystemmodule', cascade='all'),
        primaryjoin='SubSystemModule.PID==Product.PID')

if __name__ == '__main__':
    print 'SQLAlchemy version:',sa_ver
    from sqlalchemy.orm import compile_mappers
    compile_mappers()


-- 
Mike Conley

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to