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 [email protected].
To unsubscribe from this group, send email to
[email protected].
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()