I have implemented a (simplified) one-to-many relationship which works, but
I suspect I am reimplementing functionality in a suboptimal fashion which
is already done by SQLAlchemy.  The following short example:

====8<-----------------------
#!/usr/bin/env python

import datetime
from sqlalchemy import create_engine, Column, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref
from sqlalchemy.schema import UniqueConstraint
from sqlalchemy.dialects.sqlite import INTEGER, TEXT, DATETIME

Base = declarative_base()
Session = sessionmaker()
engine = create_engine('sqlite:///test.db', echo=True)

class Subordinate(Base):
    __tablename__ = 'subordinate'

    id = Column(INTEGER, primary_key=True)
    name = Column(TEXT, unique=True, nullable=False)
    discovered = Column(DATETIME, nullable=False)
    discontinued = Column(DATETIME, nullable=True)

    def __init__(self, name):
        """constructor"""
        self.name = name
        self.discovered = datetime.datetime.now()

    def __repr__(self):
        """string representation overload"""
        return '<subordinate("%d","%s","%s")>' % (self.id, self.discovered,
self.discontinued)

class Record(Base):
    __tablename__ = 'record'

    id = Column(INTEGER, primary_key=True)
    subordinate_id = Column(INTEGER, ForeignKey('subordinate.id'),
nullable=False)
    timestamp = Column(DATETIME, nullable=False)
    UniqueConstraint('subordinate_id', 'timestamp', name='occurrence')

    def __init__(self, subordinate):
        """constructor"""
        self.subordinate_id = subordinate.id
        self.timestamp = datetime.datetime.now()

    def __repr__(self):
        """string representation overload"""
        return '<Snapshot("%s","%s","%s")>' % (self.id,
self.subordinate_id, self.timestamp)

if __name__ == '__main__':
    Session.configure(bind=engine)
    session = Session()

    Base.metadata.create_all(engine)

    d = {'subordinates':{}, 'records':{}}

    lst = []
    for p in ('abc', 'ijk', 'xyz'):
        d['subordinates'][p] = Subordinate(p)
        lst.append(d['subordinates'][p])
    session.add_all(lst)
    session.commit()

    lst = []
    for p in ('abc', 'ijk', 'xyz'):
        d['records'][p] = Record(d['subordinates'][p])
        lst.append(d['records'][p])
    session.add_all(lst)
    session.commit()
====8<-----------------------
I am finding it curious in the following output that once the subordinate
tuples are committed, SQLAlchemy is querying the database once again to
retrieve the primary keys of the second table.  Am I performing too much
work in client code?

Any insight shared would be appreciated.

====8<-----------------------
2013-04-03 13:35:38,291 INFO sqlalchemy.engine.base.Engine ()
2013-04-03 13:35:38,293 INFO sqlalchemy.engine.base.Engine COMMIT
2013-04-03 13:35:38,297 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2013-04-03 13:35:38,299 INFO sqlalchemy.engine.base.Engine INSERT INTO
subordinate (name, discovered, discontinued) VALUES (?, ?, ?)
2013-04-03 13:35:38,300 INFO sqlalchemy.engine.base.Engine ('abc',
'2013-04-03 13:35:38.296111', None)
2013-04-03 13:35:38,301 INFO sqlalchemy.engine.base.Engine INSERT INTO
subordinate (name, discovered, discontinued) VALUES (?, ?, ?)
2013-04-03 13:35:38,301 INFO sqlalchemy.engine.base.Engine ('ijk',
'2013-04-03 13:35:38.296223', None)
2013-04-03 13:35:38,302 INFO sqlalchemy.engine.base.Engine INSERT INTO
subordinate (name, discovered, discontinued) VALUES (?, ?, ?)
2013-04-03 13:35:38,302 INFO sqlalchemy.engine.base.Engine ('xyz',
'2013-04-03 13:35:38.296309', None)
2013-04-03 13:35:38,303 INFO sqlalchemy.engine.base.Engine COMMIT
2013-04-03 13:35:38,305 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2013-04-03 13:35:38,306 INFO sqlalchemy.engine.base.Engine SELECT
subordinate.id AS subordinate_id, subordinate.name AS subordinate_name,
subordinate.discovered AS subordinate_discovered, subordinate.discontinued
AS subordinate_discontinued
FROM subordinate
WHERE subordinate.id = ?
2013-04-03 13:35:38,306 INFO sqlalchemy.engine.base.Engine (1,)
2013-04-03 13:35:38,309 INFO sqlalchemy.engine.base.Engine SELECT
subordinate.id AS subordinate_id, subordinate.name AS subordinate_name,
subordinate.discovered AS subordinate_discovered, subordinate.discontinued
AS subordinate_discontinued
FROM subordinate
WHERE subordinate.id = ?
2013-04-03 13:35:38,309 INFO sqlalchemy.engine.base.Engine (2,)
2013-04-03 13:35:38,311 INFO sqlalchemy.engine.base.Engine SELECT
subordinate.id AS subordinate_id, subordinate.name AS subordinate_name,
subordinate.discovered AS subordinate_discovered, subordinate.discontinued
AS subordinate_discontinued
FROM subordinate
WHERE subordinate.id = ?
2013-04-03 13:35:38,311 INFO sqlalchemy.engine.base.Engine (3,)
2013-04-03 13:35:38,313 INFO sqlalchemy.engine.base.Engine INSERT INTO
record (subordinate_id, timestamp) VALUES (?, ?)
2013-04-03 13:35:38,313 INFO sqlalchemy.engine.base.Engine (1, '2013-04-03
13:35:38.308225')
2013-04-03 13:35:38,314 INFO sqlalchemy.engine.base.Engine INSERT INTO
record (subordinate_id, timestamp) VALUES (?, ?)
2013-04-03 13:35:38,314 INFO sqlalchemy.engine.base.Engine (2, '2013-04-03
13:35:38.310071')
2013-04-03 13:35:38,315 INFO sqlalchemy.engine.base.Engine INSERT INTO
record (subordinate_id, timestamp) VALUES (?, ?)
2013-04-03 13:35:38,315 INFO sqlalchemy.engine.base.Engine (3, '2013-04-03
13:35:38.311947')
2013-04-03 13:35:38,315 INFO sqlalchemy.engine.base.Engine COMMIT
====8<-----------------------

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to