Hi.
I am trying to wrap a polymorphic model so that it can act as a traversal
node in a Pyramid application:
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
# This is the class we wish to wrap
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer, primary_key=True)
name = Column(String(50))
type = Column(String(20))
__mapper_args__ = {
'polymorphic_on': type,
'polymorphic_identity': 'employee'
}
class Manager(Employee):
__mapper_args__ = {
'polymorphic_identity': 'manager'
}
class Engineer(Employee):
__mapper_args__ = {
'polymorphic_identity': 'engineer'
}
class EmployeeInTraversal(Employee):
"""
Wraps the Employee class. This is to keep our models and our application
logic decoupled.
"""
def __getitem__(self, key):
"""
Make the employee behave like a traversal node.
:param key:
The traversal key. If asked for tasks return the appropriate
root
factory
"""
if key == 'tasks':
return 'TasksRootFactory()'
raise KeyError
# Create the tables
Base.metadata.create_all(engine)
# Create both a Manager and an Engineer
manager = Manager(name='Taylor')
engineer = Engineer(name='Sam')
session = Session()
session.add_all([manager, engineer])
session.commit()
# somewhere a request is made for /employee/1/tasks...
# Query for the engineer, somewhere in the EmployeeRootFactory
wrapped_engineer = session.query(EmployeeInTraversal).get(1)
# Traversal doing its thing. Here lies the trouble.
engineer_tasks = wrapped_engineer['tasks']
The last line of this code throws a TypeError with the message *'NoneType'
object has no attribute '__getitem__'*. Nothing is turned up by the query
to EmployeeInTraversal. If the query is instead made with the Employee
class, we get a similar TypeError: *'Manager' object has no attribute
'__getitem__'*. So in other words, querying EmployeeInTraversal returns
nothing, but querying Employee returns the object, although unwrapped.
The reason for this, near as I can tell, is that the EmployeeInTraversal
class is being interpreted as a subtype of Employee rather than as a
wrapper for the class. I attribute this to the polymorphic nature of the
Employee class, but at this point I'm really just banging my head against
the wall. We would very much like to keep our models and application logic
separate, and not embed traversal logic in the schema classes... Is there
any way to wrap a polymorphic class without the wrapper being interpreted
as a sub-type?
--
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.