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'


Gives:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/tmp/Python6244Mux.py", line 40, in <module>
    class Foo(Base):
  File
"/usr/lib/python2.6/site-packages/SQLAlchemy-0.7.4-py2.6-linux-x86_64.egg/sqlalchemy/ext/declarative.py",
line 1273, in __init__
    _as_declarative(cls, classname, cls.__dict__)
  File
"/usr/lib/python2.6/site-packages/SQLAlchemy-0.7.4-py2.6-linux-x86_64.egg/sqlalchemy/ext/declarative.py",
line 1177, in _as_declarative
    if not table.c.contains_column(c):
AttributeError: 'object' object has no attribute 'c'

Hm, maybe I can try to add the column override later?

Thanks again

peter.

On Thu, Dec 22, 2011 at 4:41 PM, Michael Bayer <mike...@zzzcomputing.com>wrote:

>
> On Dec 22, 2011, at 9:37 AM, peter sabaini wrote:
>
> > Hey list,
> >
> > this sounds like it should be a FAQ, didn't find anything though:
> >
> > I want to use the ORM in a declarative style and have the table
> > definition reflected, eg sth like:
> >
> > class A(declarative_base()):
> >    __tablename__ = 'A'
> >    __table_args__ = {'autoload' : True}
> >
> > However to do this SA (quite reasonably, really) already needs an
> > engine. For various reasons I can only construct one after import time
> > however. Is there a way to do a kind of "late reflection", ie. have
> > the above class definition but trigger the reflection part later? I
> > could of course generate the class object later in a function when the
> > engine is already available but maybe there's something more
> > elegant...
>
> I was about to type up this recipe on the wiki and then most awesomely I
> already did it for someone !   hooray.  The current technique for this is
> at
> http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DeclarativeReflectedBase.
>
>
> --
> 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.
>
>


-- 
http://sabaini.at

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