SQLAlchemy自引用模型

时间:2017-11-11 21:20:27

标签: python sqlalchemy

我正在构建一个存储具有一组属性的电子邮件的模型:

email_list_table = Table('email_list', Base.metadata,
                         Column('email_id', String, ForeignKey('emails.id')),
                         Column('list_id', Integer, ForeignKey('lists.id'))
                        )

class Email(Base):
  __tablename__ = 'emails'

  id = Column(String, primary_key=True)
  from_email = Column(String, nullable=False)
  from_name = Column(String, nullable=False)
  date = Column(DateTime, nullable=False)
  in_reply_to = Column(String)
  subject = Column(String, nullable=False)
  content = Column(String, nullable=False)
  lists = relationship("List", secondary=email_list_table)
  references = relationship("Email") # This is the issue 

  def __repr__(self):
    return "<Email(id='%s', from='%s', subject='%s')>" % (self.id, self.from_name, self.subject)

class List(Base):
  __tablename__ = 'lists'

  id = Column(Integer, primary_key=True)
  name = Column(String, nullable=False)
  email = Column(String, nullable=False)
  description = Column(String, nullable=False)

  def __repr__(self):
    return "<List(id='%s')>" % (self.id)

我想将references关系表示为电子邮件列表。例如,电子邮件可以引用多个其他电子邮件,并被多个电子邮件引用。

在传统的SQL中,我会使用第二个表,其中包含referrer_idreferenced_id的复合主键,在查询时,我会加入这两个表来获取引用的电子邮件列表。这样可以很容易地找到给定ID引用的电子邮件以及给定ID引用的电子邮件。

我查看了SQLAlchemy上Adjacency List Relationships的文档,但我不确定那里的示例是否适用于我的模型(我想我可以为referrer_id添加一列,但那不会&# 39;使用&#39; join&#39;表生成与我预期相同的表格结构。

使用SQLAlchemy制作模型的最佳/最正确方法是什么?

1 个答案:

答案 0 :(得分:0)

我通过创建第二个表并在Email类中引用它来得到我想要的答案:

email_references = Table('email_references', Base.metadata,
                         Column('referencer_id', String, ForeignKey('emails.id'), primary_key=True),
                         Column('referenced_id', String, ForeignKey('emails.id'), primary_key=True)
                    )

class Email(Base):
    __tablename__ = 'emails'

    id = Column(String, primary_key=True)
    from_email = Column(String, nullable=False)
    from_name = Column(String, nullable=False)
    date = Column(DateTime, nullable=False)
    in_reply_to = Column(String)
    subject = Column(String, nullable=False)
    content = Column(String, nullable=False)
    lists = relationship("List", secondary=email_list_table)
    references = relationship("Email",
                              secondary=email_references,                              
                        primaryjoin=id==email_references.c.referencer_id,
                          secondaryjoin=id==email_references.c.referenced_id
                         )