Please note: this project is inactive since early 2006

 
2.4.7.4 Inverse relationships

Most of the times, a RToOne relationship is the inverse of a RToMany. That's why they both have a field inverse, which allows you to identify the inverse relationship.

When you define both RToOne and RToMany with explicit source- and destination attributes (using the fields, resp., src and dst), a PyModel does not need this information to know that the two relationships are inverse for each other: a simple inspection of the relationships makes it noticeable that their source/destination entity and attributes are the same, which allows it to deduce that they are inverse to each other.

However, when you use the automatic and implicit declaration of source and destination attributes, you must supply the inverse keyword, otherwise you won't get what you expect. Suppose you declare something like this:

   self.model.entities = [
     Entity('Employee',
             properties=[ RToOne('toStore', 'Store'),
                          ] ),
      Entity('Store',
             properties=[RToMany('toEmployees','Employee'),
                          ] ),
      ]

Now see what happens (we suppose here that you have read how automatic binding of source and destination attributes is done, as described in 2.4.7):

  1. the PyModel examine the first RToOne; given that neither src nor dst are supplied, its destination attribute is automatically bound to the Store's primary key, and a AForeignKey is created, named 'fkStore', and assigned to the source attribute.

  2. Now the PyModel examine the other RToMany relationship. The source attribute is automatically bound to Store's primary key. What about the destination attribute? As expected, a foreign key should be created then bound; but since a attribute 'fkStore' already exists (created at the previous step), a foreign key named 'fkStore1' is created and bound to the destination attribute.

So: two foreign keys were created in entity Store, one for each relationship defined. As a consequence, and since the two relationships use their own foreign key, they cannot be considered as inverse to each other.

This is why you must supply the inverse attribute when designing a relationship and its inverse. When it is supplied, the automatic generation of foreign key detects it and, rather than re-creating an other foreign key such as above in step 2., re-uses the foreign key that was previously created in step 1. Hence, the following declaration is correct:

   self.model.entities = [
     Entity('Employee',
             properties=[ RToOne('toStore', 'Store', inverse='toEmployees'),
                          ] ),
      Entity('Store',
             properties=[RToMany('toEmployees','Employee',inverse='toStore'),
                          ] ),
      ]

Note: It is not required that both relationships defines the inverse attribute: it is sufficient to declare it in one of the two relationships (either the RToOne or the RToMany). However and as a general rule, we think that it makes a pymodel clearer if you define it in both relationships, and we suggest that you do that.

Comments are welcome: Sebastien Bigaret / Modeling Home Page
Hosted by:SourceForge.net Logo