Michael,

Thanks for your reply. I have been trying what you suggested as well
as several variants
and I keep getting stuck with something along the lines of:

FlushError: New instance [EMAIL PROTECTED] with identity key
(<class 'models.
dbmodel.Node'>, (2L,), None) conflicts with persistent instance
[EMAIL PROTECTED]
510

when I try to commit the new object.

I think this is because SQLAlchemy is trying to create a new Node as
well as a new VersionNode and a new Individual.
However I want to use the old Node not the new Node.

I also tried taking Node out of the inheritance tree and just making
it a straight relation to VersionNode. This worked fairly well except
when I went to related to Nodes together, since Node no longer had any
of the polymorphic knowledge of the tree, It didn't know what kind of
Node it had, it just had a node.

I am enclosing a simplified SQLlite version of the code that produces
the error above if you want to try it out. Any help you could give
would be greatly appreciated.

from sqlalchemy import *
from sqlalchemy.orm import *

db = create_engine('sqlite:///:memory:', echo=True)

metadata = MetaData()

Session = sessionmaker(bind=db, autoflush=True, transactional=True)

nodes_table = Table('nodes', metadata,
                   Column('id', Integer, Sequence('node_id_seq'),
primary_key=True),
                   Column('type', String(50), nullable=False),
                   )

versionnodes_table = Table('versionnodes', metadata,
                           Column('id', Integer,
ForeignKey('nodes.id'), primary_key=True),
                           Column('vernum', Integer, primary_key=True,
default=1),
                           )

individual_table = Table('individual', metadata,
                         Column('id', Integer(), primary_key=True),
                         Column('vernum', Integer, primary_key=True),
                         Column('sex', String(1)),
                         ForeignKeyConstraint(['id','vernum'],
['versionnodes.id','versionnodes.vernum'], ondelete="CASCADE")
                         )

node_relation_table = Table('noderelations', metadata,
                            Column('id1', Integer,
ForeignKey('nodes.id'), primary_key=True),
                            Column('id2', Integer,
ForeignKey('nodes.id'), primary_key=True)
                            )

class Node(object):
    pass

class VersionNode(Node):
    def IncrementVersion(self):
        session = Session()
        maxversion =
session.execute(select([func.max(versionnodes_table.c.vernum)],versionnodes_table.c.id==self.id)).scalar()
        self.vernum = maxversion + 1

class Individual(VersionNode):
    def create_new_version(self):
        v = Individual()
        v.sex = self.sex
        v.id = self.id
        v.IncrementVersion()
        return v

mapper(Node, nodes_table, polymorphic_on=nodes_table.c.type,
polymorphic_identity='node',
       properties={'childnodes':relation(Node,
secondary=node_relation_table,
 
primaryjoin=nodes_table.c.id==node_relation_table.c.id1,
 
secondaryjoin=nodes_table.c.id==node_relation_table.c.id2,
                                           backref='parentnodes'),
                   }
       )

mapper(VersionNode, versionnodes_table, inherits=Node,
polymorphic_identity='versionnode')
mapper(Individual, individual_table, inherits=VersionNode,
polymorphic_identity='individual')

def CreateTables():
    metadata.create_all(bind=db)

def DropTables():
    metadata.drop_all(bind=db)

CreateTables()
ind = Individual()
ind.sex = 'M'
session = Session()
session.save(ind)
session.commit()
newind = ind.create_new_version()
session.save(newind)
session.commit()

On Mar 25, 10:18 pm, Michael Bayer <[EMAIL PROTECTED]> wrote:
> having a composite primary key implies that each row contains a unique
> identity.  So you'd create a copy of your mapped instance as a new
> object and save() that to the session.  You can add a
> "create_new_version()" method to your class which does something along
> the lines of:
>
> class MyObject(object):
>     def create_new_version(self):
>         v = MyObject()
>         for k in ['attr1', 'attr2', 'attr3', ...]:
>             setattr(v, getattr(self, k))
>         return v
>
> But I think just sticking with standard ORM semantics and making a
> simple copy method is the most straightforward and readable approach.
> That way, creating a new version is as easy as:
>
>    session.save(myobject.create_new_version())
>

--~--~---------~--~----~------------~-------~--~----~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to