Flask应用SQLAlchemy多表查询:获取未被当前用户审核的文件名
解决Flask-SQLAlchemy查询未审核图片的问题
嘿,刚上手Flask和SQLAlchemy遇到关联查询的问题太正常啦,我来帮你理清楚怎么实现你要的需求!
首先,先对照你给出的表结构,我写出对应的ORM模型(你可以根据自己的实际代码调整细节):
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class User(db.Model): user_id = db.Column(db.Integer, primary_key=True) first_name = db.Column(db.String(50)) last_name = db.Column(db.String(50)) class Picture(db.Model): filename = db.Column(db.String(100), primary_key=True) picture_type = db.Column(db.String(50)) painter = db.Column(db.String(100)) class Comment(db.Model): # 联合主键,确保一个用户对同一张图只能评论一次 user_id = db.Column(db.Integer, db.ForeignKey('user.user_id'), primary_key=True) filename = db.Column(db.String(100), db.ForeignKey('picture.filename'), primary_key=True) comment = db.Column(db.Text)
你的核心需求是:筛选出指定picture_type的图片,且当前用户还没有对这些图片发表过评论(即未审核)。这里给你两种易懂的实现方式,你可以根据场景选择:
方式一:NOT IN + 子查询(直观易懂,适合新手)
这种写法逻辑非常直接:先找出当前用户已经评论过的所有图片文件名,再从Picture表中排除这些文件名,同时筛选指定类型。
# 替换成你的当前用户ID,比如从Flask Session获取:session.get('user_id') # 如果用Flask-Login,直接用current_user.user_id即可 current_user_id = 1 # 子查询:获取当前用户已评论的所有图片文件名 user_commented_files = db.session.query(Comment.filename).filter(Comment.user_id == current_user_id) # 主查询:筛选指定类型且不在已评论列表中的图片 unreviewed_pics = Picture.query.filter( Picture.picture_type == "你的目标类型", # 替换成实际要筛选的类型,比如"oil_painting" Picture.filename.not_in(user_commented_files) ).all() # 如果只需要文件名列表(不需要完整的Picture对象),可以用with_entities优化查询 unreviewed_filenames = Picture.query.with_entities(Picture.filename).filter( Picture.picture_type == "你的目标类型", Picture.filename.not_in(user_commented_files) ).all() # 把查询结果转成纯字符串列表 unreviewed_filenames = [filename[0] for filename in unreviewed_filenames]
方式二:左连接(Left Join)+ 空值筛选(性能更优)
当数据量较大时,左连接的写法通常比子查询更高效——数据库对连接操作的优化普遍更好。思路是将Picture表和Comment表左连接(关联条件为文件名匹配且评论属于当前用户),然后筛选出没有匹配到Comment记录的图片(也就是用户没评论过的)。
current_user_id = 1 unreviewed_pics = Picture.query.join( Comment, # 连接条件:文件名相同,且评论属于当前用户 (Picture.filename == Comment.filename) & (Comment.user_id == current_user_id), isouter=True # 左连接:保留所有Picture记录,即使没有对应的Comment ).filter( Picture.picture_type == "你的目标类型", Comment.user_id.is_(None) # 筛选出没有匹配到评论的图片 ).all() # 同样,获取文件名列表的写法: unreviewed_filenames = Picture.query.with_entities(Picture.filename).join( Comment, (Picture.filename == Comment.filename) & (Comment.user_id == current_user_id), isouter=True ).filter( Picture.picture_type == "你的目标类型", Comment.user_id.is_(None) ).all() unreviewed_filenames = [filename[0] for filename in unreviewed_filenames]
小提醒
- 记得替换代码里的占位符:
current_user_id要换成你实际获取当前用户ID的方式,"你的目标类型"换成你要筛选的图片类型值。 - 如果你的模型字段名和示例有差异(比如
picture_type叫img_type),记得对应修改。
内容的提问来源于stack exchange,提问作者Kay
相关产品推荐
相关产品推荐

