表关系
前言
表关系建立的前提是使用数据 库外键。总体分为三种:一对一、一对多、多对多。
外键
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) # 包含该文章