In this "How To", you will learn to create a One-to-One Relationship, a
One-to-Many Relationship, a Many-to-Many Relationship, and finally a
One-to-Many Container Relationship.
One-to-One (1:1) Relationships
Example of 1:1 Server to Admin Relationship
...
from Products.ZenRelations.RelSchema import *
...
class Server(Device):
...
_relations = (
...
("admin", ToOne(ToOne, "Admin", "server")),
...
) + Device._relations
...
...
class Admin(TestBaseClass):
...
_relations = (
...
("server", ToOne(ToOne, "Server", "admin")),
...
)
...
...
The Server object is an example of a class that inherits from
Device. According to this relationship there can be only one Admin
assigned to a Server and only one Server assigned to an Admin. This
relationship is created by:
- Importing ToOne from Products.ZenRelations.RelSchema.
- Appending a 2 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. In this case the ToOne constructor creates/returns that "RelSchema" object
- ToOne constructors takes 3 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 seconds parameter is a "string" object, "remoteClass"
which is the class name of the relative. In this case it is again a
ToOne relationship.
- The third parameter is a "string" object, "remoteName" which the remote name of itself.
- Appending a complementary 2 item tuple to the _relations attribute in the relative class.
One-to-Many (1:N) Relationships
This is a real example which illustrates a one-to-many relationship between one Location and many Devices.
From Device.py...
...
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 + (
...
("location", ToOne(ToMany, "Location", "devices")),
...
)
...
...
From Location.py...
...
from Products.ZenRelations.RelSchema import *
...
class Location(DeviceOrganizer):
...
# Organizer configuration
dmdRootName = "Locations"
portal_type = meta_type = event_key = 'Location'
_relations = DeviceOrganizer._relations + (
...
("devices", ToMany(ToOne,"Device","location")),
...
)
...
...
According to this relationship there can be only one Location
assigned to a Device but more than one Device assigned to a Location.
This relationship is created by:
- Importing ToOne and ToMany from Products.ZenRelations.RelSchema.
- Appending a 2 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 takes 3 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 seconds 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 2 item tuple to the _relations attribute in the relative class.
Many-to-Many (N:N) Relationships
This is a real example which illustrates a many-to-many relationship between many Devices and many Device Groups.
From Device.py...
...
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 2 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. In this case the ToMany constructor creates/returns the RelSchema object.
- RelSchema constructors takes 3 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 seconds 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 2 item tuple to the _relations attribute in the relative class.
One-to-Many (1:N) Container Relationships
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 2 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 takes 3 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 seconds 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 2 item tuple to the _relations attribute in the relative class.
Specifying the remoteClass in a Relationship
The remoteClass parameter can be specified in a releationship 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.DeviceOrganizer.py
class DeviceOrganizer(ZenModelRM):
...
_relations = (
...
("menus", ToManyCont(ToOne, "Products.ZenWidget.Menu", "deviceOrg")),
...
)
...