如何使用Flask-SQLAlchemy从多表中获取数据及AttributeError报错解决
解决多表关联查询及
AttributeError问题 让我们一步步拆解你的问题,先搞清楚报错的根源,再修正多表查询的逻辑:
报错原因分析
你遇到的AttributeError: 'result' object has no attribute 'get_data'主要源于几个逻辑错误:
- 你把查询结果
data定义在路由函数外部,而且用了.first(),它返回的是一个包含maindevotee、relatives、services实例的元组,不是一个带有get_data方法的对象。 - 你的
get_data函数逻辑完全错误:data是查询结果,不是模型类或查询集,根本没有query.all()方法,也不存在get_data属性。 - 路由里的
<phonenumber>是字符串类型,但你查询时用了== 3251469870(数字),会导致匹配失败。
修正后的多表关联查询方案
我们需要调整查询逻辑,让它能正确接收URL里的手机号参数,处理关联表可能没有数据的情况,并正确构造包含三个表数据的JSON响应:
完整修正代码
@app.route('/getdata/<phonenumber>', methods=['GET']) def getdata(phonenumber): # 使用outerjoin确保即使没有亲属或服务记录,也能返回主信徒数据 results = db.session.query(maindevotee, relatives, services)\ .filter(maindevotee.phonenumber == phonenumber)\ .outerjoin(relatives, maindevotee.id == relatives.main_id)\ .outerjoin(services, maindevotee.id == services.main_id)\ .all() # 构造返回的JSON结构 devotee_list = [] for main_dev, relative, service in results: # 主信徒基础数据 devotee_data = main_dev.json() # 亲属数据(如果存在则添加,否则设为None) devotee_data['relatives'] = relative.json() if relative else None # 服务数据(如果存在则添加,否则设为None) devotee_data['services'] = service.json() if service else None devotee_list.append(devotee_data) # 处理无匹配记录的情况 if not devotee_list: return jsonify({'message': 'No devotee found with this phone number'}), 404 return jsonify({'Devotee list': devotee_list})
关键修改点说明
- 将查询逻辑移到路由内部:这样才能动态接收URL中的
phonenumber参数,避免全局变量引发的问题。 - 使用
outerjoin替代join:join是内连接,只有主表和关联表都有匹配记录时才返回;outerjoin是外连接,即使关联表没有对应记录,也会保留主表的数据,避免丢失信息。 - 正确处理查询结果:
.all()返回的是列表,每个元素是包含三个表实例的元组,我们需要逐个拆解并构造完整的JSON结构。 - 类型匹配修正:直接使用URL传入的
phonenumber字符串进行匹配,避免数字与字符串类型不匹配导致的查询失败。 - 无结果处理:当查询不到数据时,返回404状态码和提示信息,提升接口的健壮性。
额外优化建议
可以在模型类中添加ORM关系属性,让查询更简洁:
class maindevotee(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(225)) phonenumber = db.Column(db.String(225)) gothram = db.Column(db.String(225)) date = db.Column(db.String(50)) address = db.Column(db.String(250)) # 定义与relatives、services的关联关系 relatives = db.relationship('relatives', backref='main_devotee', lazy=True) services = db.relationship('services', backref='main_devotee', lazy=True) def json(self): return {'id': self.id, 'name':self.name, 'phonenumber': self.phonenumber, 'gothram': self.gothram, 'date': self.date, 'address': self.address}
之后查询可以简化为:
@app.route('/getdata/<phonenumber>', methods=['GET']) def getdata(phonenumber): main_dev = maindevotee.query.filter_by(phonenumber=phonenumber).first() if not main_dev: return jsonify({'message': 'No devotee found'}), 404 # 直接通过ORM关系获取关联数据 devotee_data = main_dev.json() devotee_data['relatives'] = [r.json() for r in main_dev.relatives] devotee_data['services'] = [s.json() for s in main_dev.services] return jsonify({'Devotee list': [devotee_data]})
这种方式更符合SQLAlchemy的ORM设计风格,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者swaroop gannamani
相关产品推荐
相关产品推荐

