Wiki

Clone wiki

sqlalchemy / UsageRecipes / GenericOrmBaseClass

A base class for ORM mapped objects. This provides the ability to pass any field as a keyword param to the constructor, and an eval'able representation when the object is printed.

Notice that it will throw an AttributeError if passed an attribute that does not match one of the mapped columns. This could be extended to other mapped relationships as well.

Also note that it does not include default values in the repr.

Example:

In [1]: import sqlalchemy as sa

In [2]: from OrmObject import OrmObject

In [3]: metadata = sa.MetaData()

In [4]: user_table = sa.Table('users', metadata,
   ...:     sa.Column('user_id', sa.Integer, primary_key=True),
   ...:     sa.Column('username', sa.Unicode(32), nullable=False),
   ...:     sa.Column('description', sa.Unicode(1000), nullable=False, default=''),
   ...: )

In [5]: class User(OrmObject): pass
   ...:

In [6]: import sqlalchemy.orm

In [7]: sa.orm.mapper(User, user_table)
Out[7]: <sqlalchemy.orm.mapper.Mapper object at 0x85c722c>

In [8]: u = User(username='Jack')

In [9]: print u
User(username='Jack')

In [10]: u = User(username='Sam', description='Great Guy')

In [11]: print u
User(username='Sam', description='Great Guy')

In [12]: u.description = ''

In [13]: print u
User(username='Sam')

In [14]: u = User(bogus='Nascar Fan')
---------------------------------------------------------------------------
<type 'exceptions.AttributeError'>        Traceback (most recent call last)
... ...

Implementation:

class OrmObject(object):
    def __init__(self, **kw):
        for key in kw:
            if key in self.c:
                setattr(self, key, kw[key])
            else:
                raise AttributeError('Cannot set attribute which is' +
                                     'not column in mapped table: %s' % (key,))

    def __repr__(self):
        atts = []
        for key in self.c.keys():
            if key in self.__dict__:
                if not (hasattr(self.c.get(key).default, 'arg') and
                        getattr(self.c.get(key).default, 'arg') == getattr(self, key)):
                    atts.append( (key, getattr(self, key)) )

        return self.__class__.__name__ + '(' + ', '.join(x[0] + '=' + repr(x[1]) for x in atts) + ')'

SQLAlchemy 0.5 Implementation:

class OrmObject(object):

    def __init__(self, **kw):
        for key in kw:
            if not key.startswith('_') and key in self.__dict__:
                setattr(self, key, kw[key])

    def __repr__(self):
        attrs = []
        for key in self.__dict__:
            if not key.startswith('_'):
                attrs.append((key, getattr(self, key)))
        return self.__class__.__name__ + '(' + ', '.join(x[0] + '=' +
                                            repr(x[1]) for x in attrs) + ')'

-- Contributed by ltbarcly(Justin Van Winkle)

SQLAlchemy 0.5 Declarative Implementation:

import sqlalchemy as sa
import sqlalchemy.ext.declarative as sa_declarative

engine = sa.create_engine('sqlite:///:memory:')
Base = sa_declarative.declarative_base(name='Base', bind=engine)

def base_repr(self):
    attrs = []
    for key in self.__dict__:
        if not key.startswith('_'):
            attrs.append((key, getattr(self, key)))
        return self.__class__.__name__ + '(' + ', '.join(x[0] + '=' +
                                                         repr(x[1]) for x in attrs) + ')'

Base.__repr__ = base_repr

Updated