if theres a bug, its that your mapper setup doesnt raise an error,  
since you are creating two conflicting "category" properties on your  
Item mapper.  in practice, the "category" backref corresponding to  
the "two" collection is probably wiping out the one corresponding to  
the "one" collection.  so you append "item" to collection "one" on  
category "c"; the backref for "item.category=c" gets fired off; that  
then fires off *its* backref which says, "append to collection two".

the nature of a bi-directional relationship is that it works in both  
ways; you append an item to the list on one side, the item's parent  
property gets set to that of the list you are adding to - and then  
vice-versa.    in the case below, you have assembled "category" as a  
backref on two different relationships - theres no way SA could  
handle that, since if you said item.category = foo, should it append  
to "one" or "two" on the category ?   similarly, what if I placed the  
same item in both the "one" collection of one Category and the "two"  
collection of another Category?  you can say "raise an error" or  
something like that but thats definitely guessing on SA's part as to  
what you might want, and is beyond the scope of what the backref  
feature is designed to accomplish.

so the solution here is to either not use the "backref" feature in  
place of a distinct "category" relation on your Item mapper which you  
handle in code, or to have two different "category" backrefs, for  
which you can then make a common accessor that returns whichever one  
is non-None (or if it detects both are non-None, then does...whatever  
you think it  should do):

class Item(object):
        category = property(lambda self: self.category_one or  
self.category_two)

mapper(Category, categoryTable,
     properties = {
         "one": relation(
                 Item, backref="category_one",
                 primaryjoin = and_(
                     categoryTable.c.id == itemTable.c.category_id,
                     itemTable.c.type == 1
                 )
         ),
         "two": relation(
                 Item, backref="category_two",
                 primaryjoin = and_(
                     categoryTable.c.id == itemTable.c.category_id,
                     itemTable.c.type == 2
                 )
         ),
     }
)



On Jan 9, 2007, at 10:17 PM, aldo wrote:

>
>
> Hi folks,
>
>
> I've come accross what I suspect to be a bug - can someone confirm  
> that this is
> a problem, and not me misunderstanding something? Here's my minimal  
> test case:
>
> ***************
>
> #!/usr/bin/env python2.5
> from sqlalchemy import *
>
> categoryTable = Table(
>     'category',
>     Column('id', Integer, primary_key=True),
>     Column('name', String(40), unique=True, nullable=False),
> )
> itemTable = Table(
>     'riskevent',
>     Column('id', Integer, primary_key=True),
>     Column('type', Integer, nullable=False),
>     Column("category_id", Integer, ForeignKey("category.id")),
> )
>
>
> class Category(object):
>     def __init__(self, name):
>         self.name = name
>
> class Item(object):
>     def __init__(self, type):
>         self.type = type
>
>     def __repr__(self):
>         return "Item(%s)"%(self.type)
>
>
> mapper(Category, categoryTable,
>     properties = {
>         "one": relation(
>                 Item, backref="category",
>                 primaryjoin = and_(
>                     categoryTable.c.id == itemTable.c.category_id,
>                     itemTable.c.type == 1
>                 )
>         ),
>         "two": relation(
>                 Item, backref="category",
>                 primaryjoin = and_(
>                     categoryTable.c.id == itemTable.c.category_id,
>                     itemTable.c.type == 2
>                 )
>         ),
>     }
> )
> imap = mapper(Item, itemTable)
>
> e = Category("foo")
> e.one.append(Item(1))
> print e.one
> print e.two
>
> ***********
>
>
> At this point, e.two wrongly contains an Item object. The crucial  
> feature of
> the code is the backrefs: the behaviour goes away when the  
> "category" backrefs
> are removed. Interestingly, if the mapper adds N properties, only  
> the last
> property will contain ALL the items added, with the remaining  
> properties acting
> correctly.
>
> I'm using the latest version of SQLAlchemy from the repository.
>
>
>
>
> Cheers,
>
>
>
>
> Aldo
>
>
>
>
>
> -- 
> Aldo Cortesi
> [EMAIL PROTECTED]
> http://www.nullcube.com
> Mob: 0419 492 863
>
> >


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