如何使用多个外键正确创建flask sqlalchemy多对多关系

2024-04-24 20:14:18 发布

您现在位置:Python中文网/ 问答频道 /正文

在Flask sqlalchemy文档中,给出了使用简单多对多关系的示例:

tags = db.Table('tags',
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
    db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
)

class Page(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tags = db.relationship('Tag', secondary=tags,
        backref=db.backref('pages', lazy='dynamic'))

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)

其中可以使用以下语法接触相关对象:

^{pr2}$

我要做的基本上就是把下面的关系加在上面的关系上:

^{3}$

因此,每个页面都有附加的标记,但是每个标记在该页面的范围内可以有多个子级。我为一个名为汽车的页面做了一个展示案例,下面是它的标签和它们各自的子标签。在

(第页)汽车:

  • 梅赛德斯
    • A系列
    • B系列
    • C系列
  • 特斯拉
    • 特斯拉跑车
    • X型
    • S型
    • 模型3

上面的所有列表项都是标记对象

我希望能够使用以下语法获取相关对象:

Page.tag.children

例如(下面是明显的伪代码,但我想弄清楚这段关系的目的是什么):

Cars.tesla.children

Tags: 对象标记iddbmodel关系tagtags
1条回答
网友
1楼 · 发布于 2024-04-24 20:14:18

我想,tag_children不需要另一个表。尝试使用SQLAlchemy邻接列表:

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('tag.id'))
    children = relationship("Tag",
                backref=backref('parent', remote_side=[id])
            )

对于此架构,您可以使用如下语法:

^{pr2}$

它是使用SQLAlchemy模型的常见语法。尝试使用它来代替建议的Cars.tesla.children。在

类似Cars['tesla'].children的东西可以通过getitem方法实现,但我认为,这是一种非常不明确的方式。在

完整代码段:

class Page(Base):

    __tablename__ = 'page'

    id = Column(Integer, primary_key=True)
    name = Column(String(256))
    tags = relationship('Tag', secondary='tags',
        backref=backref('pages', lazy='dynamic'))

    def __str__(self):
        return self.name


class Tag(Base):

    __tablename__ = 'tag'

    id = Column(Integer, primary_key=True)
    name = Column(String(256))
    parent_id = Column(Integer, ForeignKey('tag.id'))
    children = relationship(
        "Tag",
        backref=backref('parent', remote_side=[id])
    )

    def __str__(self):
        return self.name

class Tags(Base):
    __tablename__ = 'tags'

    tag_id = Column(Integer, ForeignKey('tag.id'), primary_key=True)
    page_id = Column(Integer, ForeignKey('page.id'), primary_key=True)

和测试用例:

# Create page and tags
session.add(Page(id=1, name="cars"))
session.add(Tag(id=1, name="Mercedes"))
session.add(Tag(id=2, name="A-series", parent_id=1))
session.add(Tag(id=3, name="B-series", parent_id=1))
session.add(Tag(id=4, name="C-series", parent_id=1))
session.add(Tag(id=5, name="Tesla"))
session.add(Tag(id=6, name="Tesla Roadster", parent_id=5))
session.add(Tag(id=7, name="Model X", parent_id=5))
session.add(Tag(id=8, name="Model S", parent_id=5))
session.add(Tag(id=9, name="Model 3", parent_id=5))

# Fill relation
session.add(Tags(tag_id=1, page_id=1))
session.add(Tags(tag_id=5, page_id=1))

session.commit()

print session.query(Page).get(1)  # >>> cars
print session.query(Page).get(1).tags  # >>> Mercedes, Tesla
print session.query(Page).get(1).tags[1].children  # >>> Tesla models

相关问题 更多 >