Thanks. I've got this working now, but am having trouble combining
polymorphism and multiple foreign keys to the same table. Here's
roughly what I'm doing:

class Entity(Base):
    __tablename__ = 'entities'
    id = Column(Integer, primary_key=True)
    # ...bunch of columns...
    type = Column(Unicode(20), nullable=False)
    __mapper_args__ = {'polymorphic_on': type}

class Site(Entity): # Client account
    __tablename__ = 'sites'
    __mapper_args__ = {'polymorphic_identity': u'site'}
    id = Column(Integer, ForeignKey('entities.id'), primary_key=True)
    name = Column(Unicode(50), unique=True, nullable=False)
    title = Column(Unicode(50), nullable=False)

# ...few more Entity derived models...

class Note(Entity):
    __tablename__ = 'notes'
    __mapper_args__ = {'polymorphic_identity': u'note',
                       'inherit_condition': (id == Entity.id)}
    id = Column(Integer, ForeignKey('entities.id'), primary_key=True)
    site_id = Column(Integer, ForeignKey('deals.id'), nullable=False)
    site = relation(Site, foreign_keys=site_id,
                    primaryjoin=site_id == Site.id)
    attached_to_id = Column(Integer, ForeignKey('entities.id'),
nullable=False)
    attached_to = relation(Entity, foreign_keys=attached_to_id,
                           primaryjoin=attached_to_id == Entity.id,
                    backref=backref('notes', cascade='all, delete-
orphan'))
    note = Column(Unicode(255), nullable=False)

I use Note.site to determine access rights and Note.attached_to to
determine containment. This declaration works until I try to delete a
site instance. SQLAlchemy throws up this exception:

...
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/sql/
compiler.py", line 287, in construct_params
    pd[self.bind_names[bindparam]] = bindparam.value()
TypeError: id() takes exactly one argument (0 given)

However, if I remove the backref on attached_to, everything works
fine. If I move the backref to Note.site, it fails with the same
error. If I remove attached_to* and keep the backref on site, it works
again. I'm not sure what's wrong.

Here's the full traceback, for reference.

Traceback (most recent call last):
  File "/home/jace/Projects/saproj/tests.py", line 76, in test_cascade
    self.session.delete(site)
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
session.py", line 1088, in delete
    cascade_states = list(_cascade_state_iterator('delete', state))
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
session.py", line 1534, in _cascade_state_iterator
    for (o, m) in mapper.cascade_iterator(cascade, state, **kwargs):
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
mapper.py", line 1229, in cascade_iterator
    instance, instance_mapper, corresponding_state  = iterator.next()
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
properties.py", line 703, in cascade_iterator
    instances = state.value_as_iterable(self.key, passive=passive)
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
state.py", line 128, in value_as_iterable
    x = impl.get(self, dict_, passive=passive)
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
attributes.py", line 377, in get
    value = callable_(passive=passive)
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
strategies.py", line 563, in __call__
    result = q.all()
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
query.py", line 1286, in all
    return list(self)
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
query.py", line 1394, in __iter__
    return self._execute_and_instances(context)
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
query.py", line 1399, in _execute_and_instances
    mapper=self._mapper_zero_or_none())
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/
session.py", line 737, in execute
    clause, params or {})
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/
base.py", line 1086, in execute
    return Connection.executors[c](self, object, multiparams, params)
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/
base.py", line 1149, in _execute_clauseelement
    parameters=params
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/
base.py", line 1237, in __create_execution_context
    return dialect.execution_ctx_cls(dialect, connection=self,
**kwargs)
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/
default.py", line 355, in __init__
    grp,m in enumerate(parameters)]
  File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/sql/
compiler.py", line 287, in construct_params
    pd[self.bind_names[bindparam]] = bindparam.value()
TypeError: id() takes exactly one argument (0 given)

Thanks for the help.


On May 18, 10:42 pm, Michael Bayer <[email protected]> wrote:
> Don't use None for the Column type (i.e., detected as the "null" type).  Put 
> the type explicitly.   This has been updated in the documentation recently 
> since the "None" feature can't be fully supported at this time.    
>
> On May 18, 2010, at 1:34 PM, Kiran Jonnalagadda wrote:
>
>
>
>
>
> > Is it possible to have multi-level polymorphism in SQLAlchemy? Here's
> > an example:
>
> > class Entity(Base):
> >    __tablename__ = 'entities'
> >    id = Column(Integer, primary_key=True)
> >    created_at = Column(DateTime, default=datetime.utcnow,
> > nullable=False)
> >    entity_type = Column(Unicode(20), nullable=False)
> >    __mapper_args__ = {'polymorphic_on': entity_type}
>
> > class File(Entity):
> >    __tablename__ = 'files'
> >    id = Column(None, ForeignKey('entities.id'), primary_key=True)
> >    filepath = Column(Unicode(255), nullable=False)
> >    file_type = Column(Unicode(20), nullable=False)
> >    __mapper_args__ = {'polymorphic_identity': u'file',
> > 'polymorphic_on': file_type)
>
> > class Image(File):
> >    __mapper_args__ = {'polymorphic_identity': u'image'}
> >    __tablename__ = 'images'
> >    id = Column(None, ForeignKey('files.id'), primary_key=True)
> >    width = Column(Integer)
> >    height = Column(Integer)
>
> > When I call Base.metadata.create_all(), SQLAlchemy raises the
> > following error: NotImplementedError: Can't generate DDL for the null
> > type. This error goes away if I remove the Image model.
>
> > What gives?
>
> > I sense that declaring both polymorphic_identity and polymorphic_on in
> > File isn't doing the expected thing, but I'm not sure how else to do
> > this.
>
> --
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to 
> [email protected].
> For more options, visit this group 
> athttp://groups.google.com/group/sqlalchemy?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to