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):
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.
'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'), ] ), ]
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