Flask-SQLAlchemy在创建Model实例时生成INSERT语句

时间:2013-10-28 22:02:51

标签: python sqlalchemy flask flask-sqlalchemy

我正在开发一个小项目来学习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安装的。

1 个答案:

答案 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