SQLAlchemy如何用backrefs创建各种关系?

时间:2017-06-10 20:10:17

标签: python sqlalchemy

我正在阅读关于基本关系的SQLAlchemy文档,我觉得我缺少一些关于如何创建关系声明的基本理解。当我运行我的代码时,我遇到了错误,例如:

sqlalchemy.exc.NoForeignKeysError: Can't find any foreign key relationships between 'entity' and 'category'.

sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Entity.categories - there are no foreign keys linking these tables.  Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.

我认为relationship()指令的目的是最小化手动键和id的创建。

关于一对多和多对多,多对一以及语法如何区分不同类型的关系,我对语法也有点困惑。

这是我的例子,我在其中创建一个实体和各种类来尝试各种关系:

class Entity(Base):
    __tablename__ = 'entity'
    id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False )

    # many-to-one - many entities will belong to one manufacturer
    # do i need to define the mfg_id manually?
    manufacturer_id = Column(Integer, ForeignKey('manufacturer.id'))
    manufacturer = relationship("Manufacturer")

    # one-to-many relationship where an entity will have lots of 
    # properties that belong to it. Each property will only belong to one entity
    properties = relationship("EntityProperty", backref="entity")

    # this is a many-to-many relationship mapping where entity can belong 
    # to multiple categories and you can look up entities by category
    categories = relationship("Category", backref="entities")

class EntityProperty(Base):
    __tablename__ = 'entity_property'
    id = Column(Integer, primary_key=True)
    key = Column(String(250), nullable=False )
    value = Column(String(250), nullable=False )

    # do we need to define this? or can this be implied by relationship?
    entity_id = Column(Integer, ForeignKey('entity.id'))

class Category(Base):
    __tablename__ = 'category'
    id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False )

    # Does this need to know anything about entities? Many entities 
    # can belong to a category and entities can also belong to multiple
    # categories. Usage is to look up entities that belong to a category.

class Manufacturer(Base):
    __tablename__ = 'manufacturer'
    id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False )

    # Similar to category except not all manufactures would have entities.
    # How to decouple code at this level from entity

有人能指出我正确的方向,以了解关于正确使用关系()的更多信息吗?谢谢

2 个答案:

答案 0 :(得分:1)

首先,实体表中必须有一个外键引用类别表中的列(反之亦然)以建立关系。你现在没有。 但是,如果您打算在实体和类别之间建立多对多的关系,那么请注意 SQLAlchemy many-to-many Relationships

答案 1 :(得分:0)

有时你最终会在提出问题后立即解决自己的问题。这就是我学到的东西。

我对back_populdate vs backref感到有些困惑。我想如果我添加了一个backref,我不需要在相反的类中添加外键,但这是不正确的。

所以对于一对多:

这在实体

中声明
properties = relationship("EntityProperty", backref="entity")

这是在EntityProperty中声明的,以便于进行必要的反向链接,并且是必需的:

entity_id = Column(Integer, ForeignKey("entity.id"))

在多对多的情况下,我错过了一个关联表:

cat_entity_association_table = Table("cat_entity_assocaition", Base.metadata,
    Column("category_id", Integer, ForeignKey("category.id")),
    Column("entity_id", Integer, ForeignKey("entity.id")),
)

此关联用于构建实体之间的双向链接:

categories = relationship("Category", secondary=cat_entity_association_table, back_populates="entities")

和类别:

entities = relationship("Entity", secondary=cat_entity_association_table, back_populates="categories")

何时使用外部表格存在一些歧义,但希望这也有助于其他人。