this is the testcase:

from sqlalchemy import *
from sqlalchemy.orm.session import sessionmaker
from sqlalchemy.ext.declarative import declarative_base, declared_attr

engine = create_engine('sqlite:///:memory:', echo=False)
Base = declarative_base(bind = engine)
Session = sessionmaker(bind = engine)

def setup(engine):
    Base.metadata.create_all(engine)
    Session = sessionmaker(bind=engine)
    return Session()

class InheritMixin(object):

    @declared_attr
    def __tablename__(cls):
        return cls.__name__
    @declared_attr
    def id(cls):
        if Base in cls.__bases__:
            print 'base in id(cls): ', cls
            return Column(Integer, primary_key = True)
        else:
            print 'in id(cls): ', cls, cls.__bases__[0]
            return Column(Integer, ForeignKey(cls.__bases__[0].id),
primary_key = True)
    @declared_attr
    def __mapper_args__(cls):
        if Base in cls.__bases__:
            print 'base in __mapper_args__(cls): ', cls
            return {'polymorphic_on': 'discriminator'}
        else:
            print 'in __mapper_args__(cls): ', cls, cls.__bases__[0],
cls.id, (cls.id is cls.__bases__[0].id)
            return {'polymorphic_identity': cls.__name__}

class Person(Base, InheritMixin):
    discriminator = Column(String(50))
    name = Column(String(50))

class Engineer(Person):
    job = Column(String(50))

if __name__ == '__main__':

    session = setup(engine)
    a = Person(name = 'ann')
    b = Engineer(name = 'bob', job = 'car repair')
    session.add_all([a, b])
    session.commit()
    people = session.query(Person).all()
    print people

Note that i left out the 'inherit_condition', because without there is
already a problem:

base in id(cls):  <class '__main__.Person'>
base in mapper_args(cls):  <class '__main__.Person'>
in mapper_args(cls):  <class '__main__.Engineer'> <class
'__main__.Person'> Person.id True
Traceback (most recent call last):
  File "D:\Documents\Code\Eclipse\workspace\process_data3\src
\little_tests2.py", line 40, in <module>
    class Engineer(Person):
  File "C:\Python27\lib\site-packages\sqlalchemy\ext\declarative.py",
line 1336, in __init__
    _as_declarative(cls, classname, cls.__dict__)
  File "C:\Python27\lib\site-packages\sqlalchemy\ext\declarative.py",
line 1329, in _as_declarative
    **mapper_args)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\__init__.py",
line 1116, in mapper
    return Mapper(class_, local_table, *args, **params)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line
197, in __init__
    self._configure_inheritance()
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line
473, in _configure_inheritance
    self.local_table)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\util.py", line
303, in join_condition
    "between '%s' and '%s'.%s" % (a.description, b.description, hint))
sqlalchemy.exc.ArgumentError: Can't find any foreign key relationships
between 'Person' and 'Engineer'.

What am i missing?

Cheers, Lars


On Apr 19, 4:13 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
> On Apr 19, 2012, at 6:23 AM, lars van gemerden wrote:
>
>
>
>
>
>
>
>
>
> > I am trying to my my joined inheritance code clearer, for the dynamic
> > generation of sa classes and tried to do something like this:
>
> > class InheritMixin(object):
>
> >    @declared_attr
> >    def __tablename__(cls):
> >        return cls.__name__
> >    @declared_attr
> >    def id(cls):
> >        if cls.__name__ == 'Object':
> >            return Column(Integer, primary_key = True)
> >        else:
> >            print 'in id: ', cls.__name__, cls.__bases__[0].__name__
> >            return Column(Integer,
> > ForeignKey(cls.__bases__[0].__name__ + '.id'), primary_key = True)
> >    @declared_attr
> >    def __mapper_args__(cls):
> >        if cls.__name__ == 'Object':
> >            return {'polymorphic_on': 'discriminator'}
> >        else:
> >            print 'in mapper_args: ', cls.__name__,
> > cls.__bases__[0].__name__
> >            return {'polymorphic_identity': cls.__name__,
> >                    'inherit_condition': (cls.id ==
> > cls.__bases__[0].id)}
>
> > Object = type('Object', (Base, InheritMixin), clsdict)
>
> > Where Object should be the (not necessarily direct) baseclass of all
> > inheriting classes. However I get errors: "Mapper Mapper|person|person
> > could not assemble any primary key columns for mapped table 'Join
> > object on Object(65389120) and person(65428224)' " etc ..
>
> im not sure of the cause of that error, can you attach a full test case which 
> illustrates this message being generated ?
>
>
>
> > I noticed that the method __mapper_args__(cls) is always called before
> > id(cls) (which is never called, probably due to the error.
>
> the __mapper_args__(cls) method here directly calls upon .id, so if you see 
> .id() not being called it suggests some other form of .id is being used.
>
> Is it possible that Base or something else has a conflicting "id" attribute?
>
>
>
> > Also, is there a way to add the discriminator column to the mixin (if
> > i just directly add it to the declaration, this gave another maybe
> > related error)?
>
> maybe, let's start with the general idea of the mixin you're going to send me 
> as a working script.

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