Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

I think I've seen this ORM somewhere before...

Multiple Associated Properties

See ticket #19.

Currently, Dejavu only supports automatically relating two classes via a single pair of properties. That is, given classes A and B, you can relate A.ID to B.Name, but you can't relate A.ID to B.Name and B.Nickname, for example.

It's not worth the effort or complexity to support multiple associations to the same far class; that would require that the nearKey and farKey attributes of UnitAssociation? objects be arbitrary, and that's too difficult to support (see storage.db.StorageManagerDB.join, for an example which relies on the singularity, and storeshelve is much worse).

I've found it's just as easy to fake the builtin behavior (one might say the builtin behavior is faking pure Python). I'll use the example of a Directory class which needs to be related to itself via an intermediate Relation class. Rather than using associate(), it's done by hand; here are the relevant bits of the Directory and Relation classes:

class Directory(Unit):
    """A Unit representing an entry in a Directory."""
    FullName = UnitProperty()
    Gender = UnitProperty()

    def Relation(self, expr=None):
        """Recall opposite 'Relation' Units."""
        f = logic.Expression(lambda x: x.Left == self.ID or x.Right == self.ID)
        if expr is not None:
            f += expr
        return self.sandbox.recall(Relation, f)

class Relation(Unit):
    """Represents a Relation between two Directory Units."""
    
    Left = UnitProperty(int)
    LeftType = UnitProperty()
    Right = UnitProperty(int)
    RightType = UnitProperty()
    ContactType = UnitProperty()
    
    def Directory(self, expr=None):
        """Recall opposite 'Directory' Units."""
        f = logic.Expression(lambda x: x.ID in (self.Left, self.Right))
        if expr is not None:
            f += expr
        return self.sandbox.recall(Directory, f)

...and here's a custom UnitAssociation? to recall all Directory records that are related to a given Directory:

class RelationAssociation(dejavu.UnitAssociation):
    """Unit Association for use between Directory records with Relations."""
    
    to_many = True
    
    def related(self, unit, expr=None):
        value = getattr(unit, self.nearKey)
        if value is None:
            return []
        
        f = logic.filter(**{self.farKey: value})
        if expr is not None:
            f += expr
        
        units = {}
        for rel in unit.sandbox.xrecall(Relation, logic.filter(Left=unit.ID)):
            dir = unit.sandbox.unit(Directory, ID=rel.Right)
            if dir:
                units[dir] = None
        for rel in unit.sandbox.xrecall(Relation, logic.filter(Right=unit.ID)):
            dir = unit.sandbox.unit(Directory, ID=rel.Left)
            if dir:
                units[dir] = None
        return units.keys()

Directory.associate(u'ID', Directory, u'ID',
                    RelationAssociation, RelationAssociation)