美文网首页
Flask - SQLAlchemy - 关系模型

Flask - SQLAlchemy - 关系模型

作者: SingleDiego | 来源:发表于2018-08-10 13:37 被阅读81次

一对多(one-to-many)关系

下面是一个一对多关系的例子,一个 person 可以对应多个 Address。

数据库图示
class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False)
    addresses = db.relationship('Address', backref='person', lazy=True)

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), nullable=False)
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'),
        nullable=False)

我们用 db.relationshipdb.ForeignKey 来声明两个模型间的关系。

relationship 指定了该字段关联哪个模型(Address),默认情况下 SQLAlchemy 会认为一个 Person 实例可以对应多个 Address Address;如果你想使用一对一关系,那么需要添加 uselist=False 属性。

nullable 属性指定了该字段是否可以为空值,默认为 True;由于没有对应人物的电邮毫无意义,所以这里应该设定 nullable=False

backref='person' 会在 Address 类新增一个属性,供反向引用时候调用,使用类似 my_address.person 的方法就能返回 Address 对应的 person 对象。

lazy 属性定义 SQLAlchemy 何时从数据库加载数据。它有四个属性:

  • 'select' / True (默认值)
  • 'joined' / False
  • 'subquery'
  • 'dynamic'

如何为反向引用(backrefs)定义惰性(lazy)状态呢?可以像下面那样:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False)
    addresses = db.relationship('Address', lazy='select',
        backref=db.backref('person', lazy='joined'))




多对多(many-to-many)关系

下面是一个多对多关系的例子,一个页面(page)可以有多个标签(tag),一个标签也可以为多个页面拥有。

数据库图示
tags = db.Table('tags',
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True),
    db.Column('page_id', db.Integer, db.ForeignKey('page.id'), primary_key=True)
)


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

    def __repr__(self):
        return '<Page: %r>' %self.url


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

    def __repr__(self):
        return '<Tag: %r>' %self.name
  • 'Tag' 是关系当中的右侧实体(将左侧实体看成是上级类)。

  • secondary 指定了用于该关系的关联表,就是使用我在上面定义的 tags 表 。

  • backref 定义了右侧实体如何访问该关系。在左侧,关系被命名为 tags ,在右侧我将使用 pages 来表示所有页面的列表。附加的 lazy 参数表示这个查询的执行模式。

如果您想要用多对多关系,您需要定义一个用于关系的辅助表。这里我们用 tags 表来完成这个任务。对于这个辅助表, 强烈建议不使用模型,而是采用一个实际的表。

下面来演示如何操作对应关系:

# 假设插入了 Page 和 Tag 数据
>>> p = Page.query.get(1)
>>> t1 = Tag.query.get(1)
>>> t2 = Tag.query.get(2)

# 添加关系
>>> p.tags.append(t1)
>>> p.tags.append(t2)
>>> db.session.commit()

# 删除关系
>>> p.tags.remove(t1)
>>> db.session.commit()

多对多例子的源码:https://github.com/SingleDiego/flask-SQLAlchemy-many-to-many

相关文章

网友评论

      本文标题:Flask - SQLAlchemy - 关系模型

      本文链接:https://www.haomeiwen.com/subject/jihkbftx.html