跳到主要内容

表关系

前言

表关系建立的前提是使用数据库外键。总体分为三种:一对一、一对多、多对多。

外键

class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)

# 外键引用 user 表的 id 字段
author_id = db.Column(db.Integer, db.ForeignKey("user.id"))

一对多关系

一个用户有多篇文章。在"多"的一方(Article)用外键指向"一"的一方(User),在"一"的一方用 relationship 建立反向引用:

class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(80), nullable=False)

# 反向引用:user.articles 获取该用户的文章列表
articles = db.relationship("Article", backref="author", lazy="dynamic")


class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey("user.id"))

使用:

user = User(username="zhangsan")
db.session.add(user)
db.session.flush() # 先获取 user.id

article = Article(title="第一篇文章", author_id=user.id)
db.session.add(article)
db.session.commit()

# 通过反向引用查询
articles = user.articles.all()
# 通过 backref 从文章反查作者
print(article.author.username)

一对一关系

一对一与一对多写法相同,只需要给 relationship 加上 uselist=False

class Profile(db.Model):
__tablename__ = "profile"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
bio = db.Column(db.String(255), default="")


class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), nullable=False)

profile = db.relationship("Profile", uselist=False, backref="user")

使用:

user = User(username="lisi")
user.profile = Profile(bio="hello")
db.session.add(user)
db.session.commit()
print(user.profile.bio)

多对多关系

多对多需要一张中间关联表。用 db.Table 定义关联表,再用 relationship(secondary=...) 建立关系:

# 中间表:文章与标签的多对多
article_tag = db.Table(
"article_tag",
db.Column("article_id", db.Integer, db.ForeignKey("article.id"), primary_key=True),
db.Column("tag_id", db.Integer, db.ForeignKey("tag.id"), primary_key=True),
)


class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)

tags = db.relationship("Tag", secondary=article_tag, backref="articles")


class Tag(db.Model):
__tablename__ = "tag"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False)

使用:

python_tag = Tag(name="python")
web_tag = Tag(name="web")
article = Article(title="Flask 笔记", tags=[python_tag, web_tag])
db.session.add(article)
db.session.commit()

# 通过中间关系查询
print(article.tags) # [python_tag, web_tag]
print(python_tag.articles) # 包含该文章

参考