flask多表查询操作的两种方法(使用外键和不使用外键)

1使用外键:

在Flask中使用Flask-SQLAlchemy进行连表查询时,可以通过定义模型的外键关系来实现。下面是一个如何定义模型和进行连表查询的示例:

首先,定义两个模型:

from flask_sqlalchemy import SQLAlchemy

# 初始化SQLAlchemy
db = SQLAlchemy()

# 用户模型
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

# 文章模型
class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100))
    content = db.Column(db.Text)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    author = db.relationship('User', backref='articles')

# 用户和文章的关系通过外键author_id建立
# User模型不需要额外的定义来建立关系,因为它自动拥有了backref 'articles'

接着,使用Flask-SQLAlchemy进行连表查询:

# 假设我们有一个用户和他的文章列表
user = User.query.filter_by(email='user@example.com').first()

# 查询该用户的文章
articles = user.articles
for article in articles:
    print(f"Title: {article.title}")

在上面的例子中,我们定义了一个外键author_idArticle模型中指向User模型的主键id。同时,我们使用了db.relationshipArticle模型中建立了与User模型的双向关联,这样就可以通过user.articles来获取用户的所有文章。

如果你想使用原生SQL进行查询,可以使用session.query来构建复杂的查询:

# 使用原生SQL进行连表查询
query = db.session.query(User, func.count(Article.id).label('num_articles'))
       .outerjoin(Article, User.id == Article.author_id)
       .group_by(User.id)
       .all()

# 输出每个用户的ID和他们的文章数量
for user, num_articles in query:
    print(f"User ID: {user.id}, Number of Articles: {num_articles}")

在这个例子中,我们使用outerjoinUserArticle表进行了连接,并通过group_by对查询结果进行了分组,最后通过all()获取结果。这样就可以得到每个用户的ID以及他们写的文章数量。

2.不使用外键

在Flask-SQLAlchemy中,即便不使用外键,依然可以通过SQLAlchemy的查询功能来实现表之间的关联查询。以下是如何在不定义外键的情况下,通过SQLAlchemy进行连表查询的一个示例:

首先,定义两个模型(假设这两个模型没有设置外键关系):

class Account(db.Model):
    __tablename__ = 'account'
    id = db.Column(db.Integer, primary_key=True)
    nickname = db.Column(db.String())

class Bind(db.Model):
    __tablename__ = 'bind'
    id = db.Column(db.Integer, primary_key=True)
    account_id = db.Column(db.Integer)
    other_id = db.Column(db.Integer)

接下来,可以使用SQLAlchemy的join方法来进行表连接查询。例如,要查询账户及其绑定的信息,可以这样写:

# 创建一个查询对象
query = db.session.query(Account, Bind)

# 通过on关键字指定连接的条件
query = query.join(Bind, Account, Account.id == Bind.account_id)

# 执行查询并迭代结果
for account, bind in query.all():
    print(f"Account: {account.nickname}, Bind ID: {bind.id}, Other ID: {bind.other_id}")

在上述代码中,join方法用于根据指定的条件连接AccountBind两个表。Account.id == Bind.account_id是连接的条件,表示根据账户ID来关联查询。

需要注意的是,虽然可以在不使用外键的情况下进行连表查询,但这并不是数据库设计的最佳实践。外键不仅能够帮助数据库保证引用完整性,还能够让ORM更方便地处理关联对象。如果没有外键,就需要开发者自己确保关联条件的正确性,这增加了出错的可能性。因此,在实际开发中,推荐使用外键来明确表与表之间的关系。

(扩展)backref和back_populates的区别

backrefback_populates都是SQLAlchemy中用于定义双向关系的参数,但是它们在使用方式上有所不同。

backref参数允许你在定义一方的关系时,自动在另一方创建一个反向引用。当你使用backref时,你只需要在关系定义中指定一次,SQLAlchemy会为你在反向关系的模型中创建相应的属性。backref通常接受一个字符串作为参数,这个字符串是反向关系属性的名称。

例如:

class Parent(Base):
    children = relationship("Child", backref="parent")

class Child(Base):
    pass

在这个例子中,通过backref="parent",SQLAlchemy知道在Child模型中自动创建一个名为parent的属性,它引用的是Parent实例。

back_populates参数则需要在两个相关联的模型中都显式指定。它用于建立两个关系之间的明确对应关系。当你使用back_populates时,你需要在两个关系定义中都包含这个参数,以确保两个方向的关系能够正确同步。

例如:

class Parent(Base):
    children = relationship("Child", back_populates="parent")

class Child(Base):
    parent = relationship("Parent", back_populates="children")

在这个例子中,back_populates确保了Parentchildren关系和Childparent关系能够保持同步。

总结一下,backref提供了一种便捷的方式来自动创建反向关系,而back_populates提供了更明确和可控的方式来管理双向关系。在一些复杂的关系场景中,back_populates可能更加适合,因为它允许你更精确地控制关系的配置。

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请把代码喂我嘴里

您的支持是,是小弟的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值