This is a real example from Device.py
which illustrates a many-to-many relationship between many Devices and many Device Groups.
... from Products.ZenRelations.RelSchema import * ... class Device(ManagedEntity, Commandable): ... event_key = portal_type = meta_type = 'Device' default_catalog = "deviceSearch" #device ZCatalog relationshipManagerPathRestriction = '/Devices' ... _relations = ManagedEntity._relations + ( ("groups", ToMany(ToMany, "DeviceGroup", "devices")), ) ...
From DeviceGroup.py
... from Products.ZenRelations.RelSchema import * ... class DeviceGroup(DeviceOrganizer): ... # Organizer configuration dmdRootName = "Groups" portal_type = meta_type = event_key = 'DeviceGroup' _relations = DeviceOrganizer._relations + ( ("devices", ToMany(ToMany,"Device","groups")), ) ...
According to this relationship there can be more than one Device assigned to a Device Group and more than one Device Group assigned to a Device. This relationship is created by:
Importing ToMany
from Products.ZenRelations.RelSchema
.
Appending a two-item tuple to the _relations attribute
The first item in the tuple is a "string" object which is the local name
The second item in the tuple is a RelSchema
object which represents the relationship to another class. In this case the ToMany
constructor creates/returns the RelSchema
object.
The RelSchema
constructors take three parameters
The first parameter is a "type" object, "remoteType" which represents the relationship from another class. The "type" should be of a class derived from RelSchema
The second parameter is a "string" object, "remoteClass" which is the class name of the relative. In this case it is again the ToMany
relationship.
The third parameter is a "string" object, "remoteName" which the remote name of itself.
Appending a complementary two-item tuple to the _relations attribute in the relative class.
Device to Hard Drives
This is a real example which illustrates a one-to-many relationship between one DeviceHW and many HardDrives where a DeviceHW object contains HardDrives.
From DeviceHW.py
... from Products.ZenRelations.RelSchema import * ... class DeviceHW(Hardware): ... meta_type = "DeviceHW" ... _relations = Hardware._relations + ( ("harddisks", ToManyCont(ToOne, "HardDisk", "hw")), ) ...
From HardDisk.py
... from Products.ZenRelations.RelSchema import * ... class HardDisk(HWComponent): ... portal_type = meta_type = 'HardDisk' ... _relations = HWComponent._relations + ( ("hw", ToOne(ToManyCont, "DeviceHW", "harddisks")), ) ...
According to this relationship there can be only one DeviceHW assigned to a HardDisk but more than one HardDisk assigned to a DeviceHW. This relationship is created by:
Importing ToOne
and ToManyCont
from Products.ZenRelations.RelSchema
.
Appending a two-item tuple of to the _relations attribute
The first item in the tuple is a "string" object which is the local name
The second item in the tuple is a RelSchema
object which represents the relationship to another class.
RelSchema constructors take three parameters
The first parameter is a "type" object, "remoteType" which represents the relationship from another class. The "type" should be of a class derived from RelSchema
The second parameter is a "string" object, "remoteClass" which is the class name of the relative.
The third parameter is a "string" object, "remoteName" which the remote name of itself.
Appending a complementary two-item tuple to the _relations
attribute in the relative class.
Specifying the remoteClass in a Relationship
The remoteClass parameter can be specified in a relationship by two methods.
("admin", ToOne(ToOne, "Admin", "server"))
In the example above "Admin" is the remote class on the relationship. For this to work properly the module "Admin" must be in the python path and it must contain a class named "Admin".
This behavior can be modified by using the attribute zenRelationsBaseModule. For instance if Admin was located in the path Products.ZenModel you could set zenRelationsBase = "Products.ZenModel". Now the remote class is in the module Products.ZenModel.Admin and the class must be Named "Admin".
If you wish to put multiple classes into one module and use them in relations you can add the class name to the end of the remoteClass value. For instance "Admin.Test" would access the module Admin with the class Test.
If the two classes in a relation are in a different packages then you can use the fully qualified path to the class. For instance here are the definitions of two classes in different packages: Products.ZenWidgets.Menu and Products.ZenModel.DeviceOrganizer.
In Products.ZenWidget.Menu.py
... class Menu(ZenModelRM): ... _relations = ( ("deviceOrg", ToOne(ToManyCont, "Products.ZenModel.DeviceOrganizer", "menus")), ) ...
In Products.ZenModel.DeviceOrgaizer.py
... class DeviceOrganizer(ZenModelRM): ... _relations = ( ("menus", ToManyCont(ToOne, "Products.ZenWidget.Menu", "deviceOrg")), ) ...