我正在开发一个小项目来学习SQLAlchemy,我正在使用Flask和Flask-SQLAlchemy。该项目旨在模拟一系列电视节目及其剧集。
我试图在SQLAlchemy中对INSERT或UPDATE(或“upserts”)的最佳实践进行总结,但我无法超越这个障碍。似乎每当我创建一个Model实例时,SQLAlchemy(或Flask-SQLAlchemy)都会发出INSERT
语句!这很奇怪,我不认为这是对的,但也许我错过了什么?
这是Episode
模型的简化版本,它使用由三列值组成的复合主键,其中一列是Show
模型的外键:
class Episode(db.Model):
title = db.Column(db.String(256))
season = db.Column(db.Integer, primary_key=True)
episode = db.Column(db.Integer, primary_key=True)
# relationships
show_id = db.Column(db.Integer, db.ForeignKey('show.id'), primary_key=True)
show = db.relationship('Show', backref=db.backref('episodes', lazy='dynamic'))
以下是似乎生成INSERT
语句的代码:
show = Show.query.filter_by(something=139).first()
ep = Episode(**{'title': 'foo',
'show': show,
'season': 39,
'episode': 1})
db.session.commit()
我猜这与我引用持久对象有关,但肯定这不应该生成INSERT
?
任何帮助表示赞赏!
我在Windows系统上使用Python 2.7。我正在使用Flask 0.10.1,Flask-SQLAlchemy 1.0和SQLAlchemy 0.8.3,所有这些都是通过pip安装的。
答案 0 :(得分:1)
您遇到的问题与所谓的cascades有关。简而言之,它的工作方式如下:如果您正在使用的对象之一已经在会话中(在本例中为Show
,因为您通过会话从数据库中查询它),那么它也将 cascade 这个与其他与此相关的对象。
如果您不想这样,有一种方法可以禁用此行为:
show = db.relationship('Show', backref=db.backref('episodes', lazy='dynamic'), cascade=None)
我不是100%确定None
是正确的值,因为我在文档中找不到这个,我只发现False
表示“使用默认值”。
作为旁注,我想知道你为什么这样做。根据我在问题描述中的内容,我宁愿这样做:
ep = Episode.query.filter(Episode.show_id == 139).filter(Episode.season == 39).filter(Episode.episode == 1).first()
if ep:
# update
else:
# create new