Re: [sqlalchemy] Wrapping polymorphic model for Pyramid traversal
this is probably more of a Pyramid question. I'm pretty allergic to traversal myself :) On Sep 3, 2014, at 2:58 PM, Milo Toor milo.t...@gmail.com wrote: 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. -- 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.
Re: [sqlalchemy] Wrapping polymorphic model for Pyramid traversal
OK, thanks for the reply Mike! On Thursday, September 4, 2014 8:45:24 AM UTC-7, Michael Bayer wrote: this is probably more of a Pyramid question. I’m pretty allergic to traversal myself :) On Sep 3, 2014, at 2:58 PM, Milo Toor milo...@gmail.com javascript: wrote: 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+...@googlegroups.com javascript:. To post to this group, send email to sqlal...@googlegroups.com javascript:. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- 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.
[sqlalchemy] Wrapping polymorphic model for Pyramid traversal
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.