三个表之间的SQLAlchemy关系

时间:2012-07-11 18:44:57

标签: python sqlalchemy python-2.7

我有三个表:设备,插槽,端口。

  1. 设备将有多个插槽
  2. 插槽将具有多个端口,但属于单个设备
  3. 端口属于单个插槽
  4. 根据我的经验,这显示为:

    1. 设备(一对多)插槽
    2. 插槽(一对多)端口
    3. 我正在尝试在我的Devices类中建立一个关系,它将为我提供所有关联的Ports对象(无论插槽如何)。我无法弄清楚。关联表看起来很接近,但我无法从周围的例子中看出如何做我想做的事。

      class Devices(Base):
        __tablename__ = 'devices'
        __table_args__ = {
          'mysql_engine' : 'MyISAM',
          'mysql_charset': 'latin1'
        }
      
        did             = Column( INTEGER, primary_key=True )
        hostname        = Column( VARCHAR(255) )
        site            = Column( INTEGER, ForeignKey('site.sid'), default=0 )
        model           = Column( INTEGER )
        fqdn            = Column( VARCHAR(255) )
      
        slots   = relationship("Slots")
        changes = relationship("PortStateLog")
        ports   = relationship("Ports", primaryjoin="and_(Slots.device==Devices.did,Ports.slot==Slots.sid)")
      
      
      class Slots(Base):
        __tablename__ = 'slots'
        __table_args__ = {
          'mysql_engine' : 'MyISAM',
          'mysql_charset': 'latin1'
        }
      
        sid         = Column( INTEGER, primary_key=True )
        device      = Column( INTEGER, ForeignKey('devices.did'), default=None )
        slot        = Column( VARCHAR(10) )
        module      = Column( INTEGER )
        slot_status = Column( INTEGER )
        card_status = Column( INTEGER )
      
        ports = relationship("Ports", primaryjoin="Ports.slot==Slots.sid")
      
      
      class Ports(Base):
        __tablename__ = 'ports'
        __table_args__ = {
          'mysql_engine' : 'MyISAM',
          'mysql_charset': 'latin1'
        }
      
        pid         = Column( INTEGER, primary_key=True )
        slot        = Column( INTEGER, ForeignKey('slots.sid'), default=None )
        port        = Column( INTEGER )
        name        = Column( VARCHAR(200) )
        status      = Column( INTEGER )
        description = Column( VARCHAR(200) )
        op_status   = Column( VARCHAR(40) )
        substatus   = Column( INTEGER(4) )
        type        = Column( INTEGER )
        clean       = Column( TINYINT(4) )
        speed       = Column( INTEGER(10) )
        duplex      = Column( CHAR(1) )
        sfp         = Column( INTEGER )
      

      以上就是我到目前为止......我只想让下面的最后一行返回所有端口:

      d = session.query(Devices).first()
      
      d.ports
      

      非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我认为在您的Devices类定义的最后一行中,端口关系定义存在问题。我不得不将其删除以在本地使用您的架构。此外,您还没有包含任何__init__函数,因此我捏造了这些函数以创建一些示例数据。

我确定您已经知道这一点,但如果您愿意迭代设备的插槽,则可以轻松使用设备的端口列表:

d1 = session.query(Devices).filter_by(hostname='host1').first()
for slot in d1.slots:
    for port in slot.ports:
        #do something with each Ports object

跳过该中间Slots级别的一种简单方法是向您的Devices类添加一些语法糖:

def ports(self):
    my_ports = []
    for slot in self.slots:
        my_ports.extend(slot.ports)
    return(my_ports)

如果您真的想要在设备与插槽的同一级别上组合端口,则需要构建AssociationProxy(而不是Association)来映射端口集合。但是,由于您没有维护多对多关系,因此AssociationProxy看起来有点过分,需要做一些工作才能让它返回一个Ports对象列表而不是一个pid列表。