Hi there, I'm trying to use the UniqueObject recipe for my project which does not use declarative_base(). However, I'm having trouble getting this to work and run into this error:
sqlalchemy.orm.exc.UnmappedInstanceError: Class '__main__.Widget' is mapped, but this instance lacks instrumentation. This occurs when the instance is created before sqlalchemy.orm.mapper(__main__.Widget) was called. Is it simply not possible to use the decorator like this when the mapping is done module-level after the class definition? If so, is declarative the recommended practice now? Here is my code: # From http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject def unique_constructor(scoped_session, hashfunc, queryfunc): def decorate(cls): def _null_init(self, *arg, **kw): pass def __new__(cls, bases, *arg, **kw): session = scoped_session() cache = getattr(session, '_unique_cache', None) if cache is None: session._unique_cache = cache = {} key = (cls, hashfunc(*arg, **kw)) if key in cache: return cache[key] else: q = session.query(cls) q = queryfunc(q, *arg, **kw) obj = q.first() if not obj: obj = object.__new__(cls) obj._init(*arg, **kw) session.add(obj) cache[key] = obj return obj cls._init = cls.__init__ cls.__init__ = _null_init cls.__new__ = classmethod(__new__) return cls return decorate from sqlalchemy import * from sqlalchemy.orm import * engine = create_engine('sqlite://', echo=True) Session = scoped_session(sessionmaker(bind=engine)) metadata = MetaData() @unique_constructor(Session, lambda name:name, lambda query, name:query.filter(Widget.name==name) ) class Widget(object): pass widget_table = Table( 'widgets', metadata, Column('id', Integer, nullable=False, primary_key=True, autoincrement=True), Column('name', String(255), nullable=False) ) Index('idx_widgets_name', widget_table.c.name, unique=True) mapper(Widget, widget_table) if __name__ == '__main__': metadata.create_all(engine) session = Session() w1, w2, w3 = Widget(name='w1'), Widget(name='w2'), Widget(name='w3') w1b = Widget(name='w1') assert w1 is w1b assert w2 is not w3 assert w2 is not w1 session.commit() -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@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.