使用flask-sqlalchemy实现关联三表的动态过滤器相关问题
问题原因
- 报错
TypeError: 'BaseQuery' object is not callable是因为你对已生成的BaseQuery对象执行了调用操作:query(User, UserInClub)的写法错误,已实例化的查询对象不能作为函数传入表参数,多表关联需要使用join方法。 - 原有代码中的关联条件
User.id==UserInClub.id错误,关联表UserInClub中存储用户外键的字段是user_id,需修正匹配逻辑。
解决方案
动态关联多表不需要重构查询对象,直接在原有查询基础上链式调用join方法即可。多俱乐部用户去重可以用distinct()或者按用户主键group_by实现,两种方案效果一致。
修正后的完整代码如下:
class User(db.Model): id = db.Column(db.Integer, primary_key=True) created_by = db.Column(db.String(64), index=True, unique=True, nullable=False) user_name = db.Column(db.String(64), index=True, unique=True, nullable=False) @classmethod def filter_user( cls, created_by, club_name=None, user_name=None, ): query = cls.query.filter_by(created_by=created_by) if user_name: query = query.filter_by(user_name=user_name) if club_name: # 链式关联两张表,写对关联外键条件 query = query.join( UserInClub, User.id == UserInClub.user_id ).join( Club, UserInClub.club_id == Club.id ).filter( Club.club_name == club_name ) # 去重方案二选一即可 # 方案1:distinct,简洁通用 query = query.distinct() # 方案2:按用户主键分组,适合需要配合聚合查询的场景 # query = query.group_by(cls.id) return query.all() class Club(db.Model): id = db.Column(db.Integer, primary_key=True) club_name = db.Column(db.String(100), unique=True, nullable=False) class UserInClub(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) club_id = db.Column(db.Integer, db.ForeignKey('club.id'), nullable=False)
补充说明
如果使用group_by方案且使用的是开启了ONLY_FULL_GROUP_BY模式的高版本MySQL,由于User.id是表主键,分组后查询用户表全字段符合SQL规范,不会报错。
内容的提问来源于stack exchange,提问作者jack west
相关产品推荐
相关产品推荐

