Python中Flask SQLAlchemy多对多关系如何进行多表查询?

Python Flask

我想要实现这样一个功能,即返回用户关注的所有标签下的所有问题,并按照问题时间顺序排序。

标签(Tag)与问题(Question)是多对多的关系,用户(User)与问题(Question)是一对多的关系

我之前直接用的 db.Table 实现多对多,现在按照狗书将关联表改成了一个 FollowTag 模型,联结查询一直不怎么理解,请问该如何实现这个功能?模型与查询怎么写?感谢!🙏

class FollowTag(db.Model):
    tag_id = db.Column(db.Integer, db.ForeignKey('tag.id'),
                       primary_key=True)
    question_id = db.Column(db.Integer, db.ForeignKey('question.id'),
                            primary_key=True)
    create_time = db.Column(db.DateTime, default=datetime.utcnow)

Python中Flask SQLAlchemy多对多关系如何进行多表查询?

4 回复

FollowTag 表需要 user_id


在Flask-SQLAlchemy中,多对多关系的多表查询主要靠关系属性和连接查询来实现。假设我们有两个模型:UserRole,通过一个关联表user_roles建立多对多关系。

首先,定义模型和关系:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

# 关联表
user_roles = db.Table('user_roles',
    db.Column('user_id', db.Integer, db.ForeignKey('users.id'), primary_key=True),
    db.Column('role_id', db.Integer, db.ForeignKey('roles.id'), primary_key=True)
)

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    roles = db.relationship('Role', secondary=user_roles, backref=db.backref('users', lazy='dynamic'))

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))

查询方法:

  1. 通过关系属性直接查询
# 查询用户的所有角色
user = User.query.get(1)
roles = user.roles  # 直接访问关系属性

# 查询角色的所有用户
role = Role.query.get(1)
users = role.users.all()
  1. 使用join进行复杂查询
# 查询拥有"admin"角色的所有用户
users = User.query.join(user_roles).join(Role).filter(Role.name == 'admin').all()

# 查询用户"john"的所有角色名
roles = Role.query.join(user_roles).join(User).filter(User.name == 'john').all()
  1. 多条件查询
# 查询既是"admin"又是"editor"的用户
from sqlalchemy import and_
users = User.query.join(user_roles).join(Role).filter(
    and_(Role.name == 'admin', Role.name == 'editor')
).all()

实际使用示例

# 获取用户及其所有角色
user_with_roles = db.session.query(User, Role).\
    join(user_roles).join(Role).\
    filter(User.id == 1).all()

for user, role in user_with_roles:
    print(f"User: {user.name}, Role: {role.name}")

关键点

  • 关系属性(user.roles/role.users)提供了最直接的访问方式
  • 对于复杂查询,使用join()连接关联表和目标表
  • 多条件查询时注意使用正确的连接逻辑

总结:多对多查询的核心是正确使用关系属性和join操作。

instances = db.session.query(Question).join( FollowTag, FollowTag.question_id=Question.id).join(Tag,Tag.id==FollowTag.tag_id).join(User,User.id==Tag.user_id).filter(User.id==查询用户 id)
…大学学得不好🤣,不知道这样有没有用

感谢,我已经解决了,这样就好了
python<br>query = db.session.query(Question)<br>query = query.filter(Question.tags.any(Tag.users.any(<a target="_blank" href="http://User.id" rel="nofollow noopener">User.id</a> == <a target="_blank" href="http://self.id" rel="nofollow noopener">self.id</a>)))<br>

回到顶部