On Aug 15, 2012, at 4:00 AM, Richard Rosenberg wrote:

> I think at this point, the docs are simply making it worse for me. Is there 
> an example out there that is declarative and concise?
> 
> This is a really simple scenario involving a single "header" table, and 
> multiple (identical) "detail" tables, as in:
> 
> headertable
>   id int
>   namekey varchar
> 
> detail1
>   id integer
>   headerid integer, fk headertable.id
>   groupid integer
>   somevalue varchar
> 
> And so on, ad nauseum, detail2. . .detailN
> 
> Employees, engineers, and managers. . .Is.Not.Working for me. Is there 
> something better out there. . ? I can make it AbstractConcreteBase or 
> ConcreteBase, or whatever at this point, any direction in the way of best 
> practice or gotchas is appreciated too.  

First note that the main inheritance docs for "latest" have been updated to be 
fully declarative for "joined" and "single" inheritance: 
http://docs.sqlalchemy.org/en/latest/orm/inheritance.html .   Concrete will 
follow.

The next step is identifying one of three patterns: single, joined, or concrete 
table inheritance.    If our docs aren't enough, here are Fowler's description 
of each : http://martinfowler.com/eaaCatalog/singleTableInheritance.html 
http://martinfowler.com/eaaCatalog/classTableInheritance.html (this is what we 
call "joined"), 
http://martinfowler.com/eaaCatalog/concreteTableInheritance.html.   Here's 
another extremely in-depth description of the various inheritance patterns, 
including ones we don't support: 
http://www.agiledata.org/essays/mappingObjects.html#MappingInheritance .    I 
should actually consider adding Fowler's links to our own docs, that's a good 
idea.

So at this point, you'd have decided which of those three patterns you're 
using.   I can already tell you that its "joined", because you have two 
separate tables (so not single) and your "base" table has a column that is not 
in the "sub" table (so not concrete).

From there, you can pretty much swap out the names in our Employee example at 
http://docs.sqlalchemy.org/en/latest/orm/inheritance.html#joined-table-inheritance
 to get at the initial "headertable" and "detail1".  

I've attached that, laying out Header and Detail1 explicitly.  Then, since you 
said you have "detail2, 3, 4,...N" I illustrate a function to create more 
Detail classes dynamically.  You can run this example as is, as it creates its 
own SQLite database.   I hope it helps!

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

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Header(Base):
    __tablename__ = 'headertable'
    id = Column(Integer, primary_key=True)
    namekey = Column(String(50))
    type = Column(String(50))

    __mapper_args__ = {
        'polymorphic_identity': 'header',
        'polymorphic_on': type
    }


class Detail1(Header):
    __tablename__ = 'detail1'
    id = Column(Integer, primary_key=True)
    headerid = Column(Integer, ForeignKey('headertable.id'))
    groupid = Column(Integer)
    somevalue = Column(String(30))

    __mapper_args__ = {
        'polymorphic_identity': 'detail1',
    }

def make_detail(id):
    # to get "N" Detail classes, this creates new Detail classes
    # dynamically
    return type(
            "Detail%d" % id,
            (Header,),
            dict(
                __tablename__='detail%d' % id,
                id=Column(Integer, primary_key=True),
                headerid=Column(Integer, ForeignKey('headertable.id')),
                groupid=Column(Integer),
                somevalue=Column(String(30)),
                __mapper_args__={
                    'polymorphic_identity': 'detail%d' % id,
                }
            )
        )

# lets make N detail classes
N = 10

for i in xrange(2, N):
    new_detail_cls = make_detail(i)
    locals()[new_detail_cls.__name__] = new_detail_cls


e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

s = Session(e)

s.add_all([
        Detail5(somevalue="d5", groupid=6),
        Detail2(somevalue="d2", groupid=7),
        Detail9(somevalue="d9", groupid=8),
        Detail5(somevalue="d5", groupid=9),
        Detail8(somevalue="d8", groupid=4),
        Detail1(somevalue="d1", groupid=5),
])
s.commit()

print s.query(Header).all()

Reply via email to