Hello Michael,

Thank you for your reply and for SA!

> you could also try the "relations" relation mapping using just a
> single "primaryjoin" across the two tables.  *or*, not even have it
> and just use a property accessor, this is the cleaner way to do it:
>
>       def _relations(self):
>               foreach x in self.relation_direct:
>                       foreach y in x.relation_inverse:
>                               yield y
>       def _add_relation(self, info):
>               info.relation_inverse.append(self)
>               self.relation_direct.append(info)
>       relations = property(_relations, _add_relation)

The yield and property() were new to me but after reading about them I
don't understand your example. If I understand correctly these are
Information methods. Both relation_inverse and relation_direct are lists
of Relationship objects so I believe I cannot append an Information object
to them.

I adapted your code while adding backreferences to the information mapper:

properties = { 'relation_direct' : relation(Relationship,
   primaryjoin=(info_table.c.pk == rel_table.c.info_fk_one),
   backref='info_direct'),
               'relation_inverse' : relation(Relationship,
   primaryjoin=(info_table.c.pk == rel_table.c.info_fk_two),
   backref='info_inverse')}
Information.mapper = mapper(Information, info_table,
                            properties = properties)
Relationship.mapper = mapper(Relationship, rel_table)

class Information(object):
    def __init__(self, info):
        self.info = info

    def _relations(self):
        for x in self.relation_direct:
            yield x.info_inverse

    def _add_relation(self, info):
        self.relation_direct.append(Relationship(self, info[0], info[1]))

    relations = property(_relations, _add_relation)

With this I can add a relation with:
i1.relations = (i4, "Father")

and get all of John's relations with:
iq1=session.query(Information).get_by(info="John")
for n in iq1.relations:
    print iq1.info + " is related to " + n.info

The problem with this approach is that a SELECT is issued to the database
in every iteration of the for loop. Any suggestions to overcome this?

>> My second question is if it is possible to do a query on
>> Information based
>> on rel_data (attribute of Relationship), like a query that returns
>> all of
>> John's nephews (rel_data = "Uncle")?
>>
>> I think the SQL output of the ORM should be something like:
>>
>> SELECT infos2.pk, infos2.info FROM infos
>>  JOIN rels ON infos.pk = rels.info_fk_one
>>  JOIN infos AS infos2 ON rels.info_fk_two = infos2.pk
>>  WHERE infos.pk = ? AND rels.rel_data = ?
>>
>
> info2 = info_table.alias('info2')
> session.query(Information).select(
>      info_table.select(
>      and_(info2.c.pk==17,rel_table.c.rel_data=='somedata'),
>      from_obj=[info_table.join(rel_table,
> info_table.c.pk==rel_table.c.info_fk_one).join(info2,
> info2.c.pk==rel_table.c.info_fk_two)]
>      )
> )

This selects on info_table but I need to select on info2. I didn't manage
to select on info2 but I turned the select around and did it like this:

info2 = info_table.alias('info2')
session.query(Information).select(
    info_table.select(
    and_(info2.c.pk==iq1.pk,rel_table.c.rel_data=='Uncle'),
    from_obj=[info_table.join(rel_table,
info_table.c.pk==rel_table.c.info_fk_two).join(info2,
info2.c.pk==rel_table.c.info_fk_one)]
    )
)

Thanks again for your help!

-- 
Rúben Leote Mendes -- [EMAIL PROTECTED]


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users

Reply via email to