一对多(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.relationship
和 db.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
网友评论