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

Reply via email to