Flask-SQLAlchemy反向迭代:如何按Piece而非Side遍历数据?
当然可以实现这个需求!不过首先得补充一下你的模型——目前的Side类里没有区分Front/Back的字段,这是实现需求的前提,因为我们需要明确每个Piece属于哪个类型的Side。
第一步:完善模型定义
给Side类添加一个side_type字段,用来标记是Front还是Back:
class Side(db.Model): id = db.Column(db.Integer, primary_key=True) job_id = db.Column(db.Integer, db.ForeignKey('job.id')) side_type = db.Column(db.String(20), nullable=False) # 新增字段,值为'Front'或'Back' pieces = db.relationship('Piece', backref='side', lazy='select')
第二步:实现需求的两种方式
方式一:用SQLAlchemy聚合查询(推荐,效率更高)
直接通过SQL分组聚合,一次性获取所有Job、Piece及其对应的Side类型:
from sqlalchemy import func, array_agg # 执行聚合查询 job_piece_data = db.session.query( Job.name, Piece.name, func.array_agg(Side.side_type).label('side_list') ).join(Side, Job.id == Side.job_id)\ .join(Piece, Side.id == Piece.side_id)\ .group_by(Job.name, Piece.name)\ .order_by(Job.name, Piece.name)\ .all() # 整理成目标格式 result = {} for job_name, piece_name, side_list in job_piece_data: # 对Side列表排序,保持和示例一致的顺序 sorted_sides = sorted(side_list) if job_name not in result: result[job_name] = {} result[job_name][piece_name] = sorted_sides # 输出结果 for job, pieces in result.items(): print(f"- {job}") for piece, sides in pieces.items(): print(f" - {piece}: {', '.join(sides)}")
方式二:Python层面遍历处理(更直观)
如果不想用SQL聚合,也可以先查询所有Job,再逐层遍历关联对象,在Python层面收集每个Piece的Side信息:
jobs = Job.query.all() result = {} for job in jobs: piece_map = {} # 遍历当前Job的所有Side for side in job.sides: # 遍历当前Side下的所有Piece for piece in side.pieces: if piece.name not in piece_map: piece_map[piece.name] = [] # 去重添加Side类型 if side.side_type not in piece_map[piece.name]: piece_map[piece.name].append(side.side_type) # 对每个Piece的Side列表排序 for p_name in piece_map: piece_map[p_name].sort() result[job.name] = piece_map # 输出结果 for job, pieces in result.items(): print(f"- {job}") for piece, sides in pieces.items(): print(f" - {piece}: {', '.join(sides)}")
最终输出结果
两种方式都会得到你期望的结构:
- Job 1 - Piece 1: Front, Back - Piece 2: Front - Job 2 - Piece 3: Front, Back - Piece 4: Front, Back
内容的提问来源于stack exchange,提问作者Ricardo Reis
相关产品推荐
相关产品推荐

