I'm using SQLAlchemy 0.7.1 on a MySQL 5.1.57 database, and I'm getting
unexpected behavior with the cascade_backrefs=False parameter for my
many-to-many relationships.

Here's the pertinent table code:

Base = declarative_base()
class ZKGroup(Base):
    __tablename__ = 'groups'

    id          = Column(Integer, primary_key=True)
    name        = Column(String(512))

    def __init__(self, name)
        self.name = name

user_groups = Table('user_groups', Base.metadata,
    Column('user_id', String(128), ForeignKey('users.username')),
    Column('group_id', Integer, ForeignKey('groups.id'))
)

class ZKUser(Base):
    __tablename__ = 'users'

    username   = Column(String(128), primary_key=True)

    groups = relationship(ZKGroup, secondary=user_groups,
backref='users', cascade_backrefs=False)

    def __init__(self, username, groups)
        self.username = username
        self.groups = groups

Now, I would expect the cascade_backrefs=False option to prevent newly
created ZKUser objects with a persistent ZKGroup object in their
'groups' list to not be added to the session.  But the ZKUser object
appears to being getting added to the session anyway.  I can tell
because this code:

group = ZKGroup('group1')
session.add(group)
user = ZKUser('user1')
session.add(user)
self.session.commit()
user2 = ZKUser('user1', [group])
session.merge(user2)
session.commit()

Throws this exception from the session.merge() call:
Traceback (most recent call last):
  File "TestScript.py", line 7
    session.merge(user2)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
lib/python2.6/site-packages/sqlalchemy/orm/session.py", line 1220, in
merge
    self._autoflush()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
lib/python2.6/site-packages/sqlalchemy/orm/session.py", line 901, in
_autoflush
    self.flush()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
lib/python2.6/site-packages/sqlalchemy/orm/session.py", line 1473, in
flush
    self._flush(objects)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
lib/python2.6/site-packages/sqlalchemy/orm/session.py", line 1542, in
_flush
    flush_context.execute()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
lib/python2.6/site-packages/sqlalchemy/orm/unitofwork.py", line 327,
in execute
    rec.execute(self)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
lib/python2.6/site-packages/sqlalchemy/orm/unitofwork.py", line 471,
in execute
    uow
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
lib/python2.6/site-packages/sqlalchemy/orm/mapper.py", line 1902, in
_save_obj
    state_str(existing)))
FlushError: New instance <ZKUser at 0x10412f3d0> with identity key
(<class 'zookeeper.common.model.ZKUser.ZKUser'>, ('user1',)) conflicts
with persistent instance <ZKUser at 0x1040fce10>

However, if I add a call to 'session.expunge(user2)' right before
'session.merge(user2)', the merge completes and user1 gets associated
to group1 in the DB, as expected.

Is this a bug with cascade_backrefs=False? Or is it just not meant to
be used with many-to-many relationships, or something like that?

-- 
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