On Dec 22, 2011, at 11:48 AM, peter sabaini wrote:

> Hey!
> 
> This works for me -- almost :-)
> 
> In my use case I need to override a column (to provide an artificial FK -- 
> some *erm old school mysql db) which seems to trigger SA into trying to 
> reflect early
> 
> Observe:
> 
> from sqlalchemy import *
> from sqlalchemy.orm import *
> from sqlalchemy.ext.declarative import declarative_base, declared_attr
> 
> class DeclarativeReflectedBase(object):
>     _mapper_args = []
> 
>     @classmethod
>     def __mapper_cls__(cls, *args, **kw):
>         """Declarative will use this function in lieu of 
>         calling mapper() directly.
>         
>         Collect each series of arguments and invoke
>         them when prepare() is called.
>         """
> 
>         cls._mapper_args.append((args, kw))
> 
>     @classmethod
>     def prepare(cls, engine):
>         """Reflect all the tables and map !"""
>         for args, kw in cls._mapper_args:
>             klass = args[0]
>             klass.__table__ = table = Table(
>                                         klass.__tablename__, 
>                                         cls.metadata, 
>                                         autoload=True, 
>                                         autoload_with=engine)
>             klass.__mapper__ = mapper(klass, table, **kw)
> 
>     @declared_attr
>     def __table__(cls):
>         """Return a placeholder to lull declarative into complacency"""
>         return object()
> 
> Base = declarative_base(cls=DeclarativeReflectedBase)
> 
> class Foo(Base):
>     __tablename__ = 'foo'
>     quux = Column(String)
>     bars = relationship("Bar")
> 
> class Bar(Base):
>     __tablename__ = 'bar'
> 
> 

yah well you want to not declare Column objects on the declared class directly 
in this case because that trips off declarative into building up a Table, which 
you don't have here, it only returns "object".

this could work really nicely with extend_existing, which has been enhanced in 
0.7.4, but there seem to be some glitches preventing it from being super nice, 
so I can't get that to work right now.  Just send in those columns via your own 
means:

class Base(object):
    # ...

    extra_cols = []

    @classmethod
    def prepare(cls, engine):
        """Reflect all the tables and map !"""
        for args, kw in cls._mapper_args:
            klass = args[0]
            klass.__table__ = table = Table(
                                        klass.__tablename__, 
                                        cls.metadata, 
                                        autoload=True, 
                                        autoload_with=engine,
                                        *klass.extra_cols
                                        )
            klass.__mapper__ = mapper(klass, table, **kw)


    class Bar(Base):
        __tablename__ = 'bar'

        extra_cols = [
                Column('foo_id', Integer, ForeignKey('foo.id')),
        ]

-- 
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