python - 如何在 Flasksqlachemy 中同时插入父表和子表?
问题描述
我将 FlaskSqlachemy 与 Postgresql 数据库一起使用。
我有一个名为 Order 的表和一个名为 Attempt (尝试交付订单)的表,它们是一对多的关系。尝试表具有 order.id 的 FK。
我想在同一个会话中将记录同时插入到 Order 和 Attempt 表中。问题是我在插入之前不知道 order.id。那是因为 order.id 是 Order 表的 PK,具有自增功能。
我可以先插入订单,然后检查 order.id,最后插入尝试。我的问题是:如果第二次插入失败,我最终会得到一个没有与之关联的尝试的订单。
在这种情况下,最佳做法是什么?
下面是我的数据库模型的简化版本:
class Order(db.Model):
id = db.Column(db.Integer, primary_key=True)
attempts = db.relationship('Attempt', backref='order', lazy='select',
order_by="Attempt.date")
class Attempt(db.Model):
id = db.Column(db.Integer, primary_key=True)
order_id = db.Column(None, db.ForeignKey('order.id'))
现在,我的解决方案如下:
# Create an order object
new_order = Order()
# Try to add it to db
try:
db.session.add(new_order)
db.session.commit()
except Exception:
....
return redirect(url_for('scheduleorder'))
else:
order = Order.query.filter_by(token=token).first()
# Create an attempt object
new_attempt = Attempt(order_id=order.id)
try:
db.session.add(new_attempt)
db.session.commit()
except Exception:
...
return redirect(url_for('scheduleorder'))
else:
...
return redirect(url_for('scheduleorder'))
解决方案
commit()
我建议不要使用which 持久化对数据库的更改,而是使用flush()
. Flush 将更改推送到数据库事务缓冲区,即您的对象已创建并放置在缓冲区内,但并未真正作为记录写入您的数据库。之所以如此,是因为在该会话中,如果发生异常,例如插入命令失败,我们将使用rollback()
方法回滚到以前的状态。
这非常适合您的用例,因为当您创建对象并使用刷新方法时,您可以访问在数据库中自动递增的 id,在您的代码中进一步使用。遇到异常时不要忘记使用 db.session.rollback() 来实际回滚事务。
# Create an order object
new_order = Order()
# Try to add it to db
try:
db.session.add(new_order)
db.session.flush()
order_id = new_order.id
except Exception:
....
db.session.rollback()
return redirect(url_for('scheduleorder'))
else:
# Create an attempt object
new_attempt = Attempt(order_id=order_id)
try:
db.session.add(new_attempt)
db.session.flush()
except Exception:
...
db.session.rollback()
return redirect(url_for('scheduleorder'))
else:
...
return redirect(url_for('scheduleorder'))
# use the commit at the end of you usecase so that you actually create a record in your database.
db.session.commit()
推荐阅读
- javascript - 无法更改 Select2 中某个选项的字体大小
- karate - 如何仅为更改的微服务执行空手道脚本
- java - Springboot:分为STARTER与CORE的依赖关系职责之间的区别
- python - 在 Python 中在一组元组上分配值
- mysql - 从 sql 中的 2 个表中删除,该表在其他表中具有外键
- xamarin.android - 以编程方式滚动列表视图
- google-compute-engine - GCloud 导入 vmdk 磁盘总是失败
- dc.js - 使用嵌套的 json 数据创建多行
- java - 如何在Java中将长度为m的整数数组转换为长度为n的数组[已解决]
- javascript - 尝试将 react-select 导入使用 create-react-app 创建的项目时出错