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 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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to