On Nov 13, 2012, at 7:59 PM, Gerald Thibault wrote:
I have a base class which has two subclasses specified via a polymorphic
discriminator, and I'm wondering how to set things up so the returned results
are instances of the subclass, when I create an instance of the base class
and assign the relevant value to the discriminator column. Here's my example
code:
that's not how it usually works. You'd create instances of the subclasses, and
leave the discriminator column alone; SQLAlchemy assigns that.
test1 = Test(type='one', name='a test')
session.add(test1)
print test1
This returns an instance of Test, not Test1, despite the discriminator
indicating that it should be cast as Test1.
OK here, you've said test = Test(). That is now the Python version of the
class, SQLAlchemy has nothing to do with changing __class__ on your Test object
or anything like that. That object is going to stay just like it is, except
for it getting a new primary key value. SQLAlchemy's job here is to persist
your row in the database and return it back for you later. Here, the session
hasn't even flushed any data, and you can see in your echo there's not any
INSERT. If you were to allow the row to go out to the database and come back,
you'd see your class:
test1 = Test(type='one', name='a test')
session.add(test1)
session.commit() # flush + commit transaction
session.close() # expunge the Test() object totally so we get a new one
back
print session.query(Test).one()
above, it's important that test1 is removed from the Session totally, so that
when we query again for that row, the Test object isn't returned; otherwise, it
still points to that row.
However, the way it's supposed to work is, just use the classes as designed
(note also, we use Session, or sessionmaker() - not create_session() which is a
legacy function used for internal testing - see
http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html for recommended usage
patterns):
from sqlalchemy.orm import Session
session = Session(e)
test1 = TestOne(name='a test')
session.add(test1)
print session.query(Test).one() # autoflushes, then gets our TestOne back
Also, if i create test1, and then do session.expunge_all, then immediately
requery for session.query(Site).get(1), the returned instance is of type
Test1, but trying to set the value for value1 yields 'Can't update table
using NULL for primary key value'.
works for me:
test1 = TestOne(name='a test')
session.add(test1)
print session.query(Test).one()
session.expunge_all()
t = session.query(Test).one()
t.value1 = value1
session.commit()
output:
BEGIN (implicit)
INSERT INTO test (type, name) VALUES (?, ?)
('one', 'a test')
INSERT INTO test1 (id, value1) VALUES (?, ?)
(1, None)
SELECT test.id AS test_id, test.type AS test_type, test.name AS test_name,
test1.id AS test1_id, test1.value1 AS test1_value1, test2.id AS test2_id,
test2.value2 AS test2_value2
FROM test LEFT OUTER JOIN test1 ON test.id = test1.id LEFT OUTER JOIN test2 ON
test.id = test2.id
()
__main__.TestOne object at 0x1014d7910
SELECT test.id AS test_id, test.type AS test_type, test.name AS test_name,
test1.id AS test1_id, test1.value1 AS test1_value1, test2.id AS test2_id,
test2.value2 AS test2_value2
FROM test LEFT OUTER JOIN test1 ON test.id = test1.id LEFT OUTER JOIN test2 ON
test.id = test2.id
()
UPDATE test1 SET value1=? WHERE test1.id = ?
('value1', 1)
COMMIT
--
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.