Flask+SQLAlchemy一对多关系下关联数据排序删除及更新报错问询
问题根因
你遇到的AttributeError: 'list' object has no attribute 'filter_by'错误,是SQLAlchemy查询方法的调用顺序错误导致的:
query.all()会立即执行SQL查询,直接返回存储查询结果的Python列表,列表对象没有过滤查询的相关方法- 你原先的写法还混淆了
filter和filter_by的用法:filter_by接收关键字参数,直接写字段名即可;filter才需要写类名.字段名的判断表达式
修复方案
你需要先加过滤条件,再执行查询/删除操作,而且删除关联数据不需要先查询再遍历删除,可以直接调用delete方法简化操作,效率更高。
核心修改点
将报错行及后续的删除逻辑:
all_comps = Company.query.all().filter_by(Company.frankendama_id == id) #Error here for entry in all_comps: if entry.frankendama_id == id: db.session.delete(entry)
替换为:
# 直接删除所有frankendama_id匹配的记录 Company.query.filter_by(frankendama_id=id).delete()
额外优化建议
- 新增公司记录时不需要每次循环都commit,全部add完成后统一提交即可,减少数据库交互,还能保证事务一致性
- 分割公司名称后可以做空格去除、空值过滤,避免用户输入不规范产生无效数据
- 主表Frankendama的修改和关联Company的修改可以放在同一个事务里提交,避免一半成功一半失败的数据不一致问题
- 编辑场景下进入表单页时可以自动填充原有数据,提升用户体验
完整修正后代码
frank = Frankendama.query.get(id) form = FrankForm() if form.validate_on_submit(): # 更新主表信息 frank.title=form.title.data frank.description=form.description.data frank.tama=form.tama.data frank.sarado=form.sarado.data frank.sword=form.sword.data frank.string=form.string.data frank.bearing=form.bearing.data db.session.add(frank) # 处理关联公司数据 comps = form.companies.data # 分割+去除空格+过滤空值 comps_used = [c.strip() for c in comps.split(",") if c.strip()] # 删除旧的关联数据 Company.query.filter_by(frankendama_id=id).delete() # 批量新增新的关联数据 for comp_name in comps_used: new_comp = Company(name=comp_name, frankendama_id=id) db.session.add(new_comp) # 统一提交所有修改 db.session.commit() return redirect(url_for("home")) else: # 填充原有数据到表单 form.process(obj=frank) return render_template("create.html", form=form)
内容的提问来源于stack exchange,提问作者MCSaunders
相关产品推荐
相关产品推荐

