【问题标题】:SQLAlchemy relationships between three tables三个表之间的 SQLAlchemy 关系
【发布时间】:2012-07-11 11:10:06
【问题描述】:

我有三个表:Devices、Slots、Ports。

  1. 设备将有多个插槽
  2. 插槽将有多个端口,但属于单个设备
  3. 端口属于单个插槽

根据我的经验,这显示为:

  1. 设备(一对多)插槽
  2. 插槽(一对多)端口

我正在尝试在我的 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

非常感谢任何帮助。

【问题讨论】:

    标签: python sqlalchemy python-2.7


    【解决方案1】:

    我认为您的 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 列表。

    【讨论】:

    • 很抱歉,我没有回复。如果它解决了我的问题,我将对此进行审查并更新此评论/批准。直到现在我才注意到这一点!
    猜你喜欢
    • 2017-07-18
    • 2013-07-01
    • 2019-08-26
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多