On Dec 11, 2007, at 1:04 AM, Scott Graham wrote:
> > mapper(User, usersTable, properties = { > 'Ys': relation(Y, backref='user'), > 'Xs': relation(X, backref='user'), > }) > mapper(X, xsTable, properties = { > 'Ys': relation(Y, secondary = X_Ys) > }) > mapper(Y, ysTable, properties={ > 'Xs': relation(X, secondary = X_Ys) > }) > one major thing to fix here is that the X->X_Y->Y relation should be configured once, and the reverse side as a backref. in the case of many-to-many, the two relations communicate with each other so that they dont both insert/update/delete from the X_Y table redundantly. > then: > >>>> u = User(...) >>>> u.Ys.append(Y(...)) >>>> u.Ys[0].Xs.append(X(...)) > >>>> u.Ys > [<Y(...)>] >>>> u.Ys[0].Xs > [<X(...)>] >>>> u.Xs > [] > > I was expecting/hoping that u.Xs would have the X that was appended to > u.Ys[0]. I can sort of make it work as long as I make the id columns > in X_Ys non-nullable. > In that case, session.commit() throws an > IntegrityError if I don't manually set the user_id in any X objects to > a user id (Y objects get their user id ok). However, when I do that: u.Xs is going to have exactly those X's which have u's id as their user_id attribute. the X which you appended to u.Ys[0] is from a different relationship. so yeah you have to set the user_id attribute on the X, which is entirely legal. However the "legit" way to do it is to just add the "X" to u's Xs collection and have the ORM take care of the user_id attribute for you. just like: x = X() u.Ys[0].Xs.append(x) u.Xs.append(x) you just manipulate the data structure in python and dont worry about any database identifiers...then the flush process takes care of it for you. >>>> u.Ys[0].Xs[0].user_id = u.id >>>> u.commit() > > I seem to have to make a new session before the changes "show up" in > the user. ie. I must do: > > sess.close() > sess = Session() > u = s.query(User).first() no you dont need to do all that. even if you are just setting "user_id" as you are now, just expire the attribute: session.expire(u, ['Xs']), and it will reload when you touch it again. but if you think in terms of collections instead of foreign keys like above, then you dont even need that, it would just all work out. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com 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 -~----------~----~----~----~------~----~------~--~---