暂时禁用 SQLAlchemy 中的增量

Temporarily disable increment in SQLAlchemy

我是 运行 带有 SQLAlchemy (1.1.0b3) 和 Postgres 的 Flask 应用程序。

对于 Flask,我提供了一个 API,客户端可以通过它获取类型数据库的所有实例,并 POST 在干净版本的 Flask 应用程序上再次获取它们,作为一种方式本地备份。当客户再次发布它们时,它们应该再次具有与他下载它们时相同的 ID。

我不想为正常操作禁用主键的 "increment" 选项,但如果客户端提供带有 POST 的 ID 并希望提供一个新资源,我会喜欢相应地设置它而不破坏 SQLAlchemy。如何才能access/reset当前ids的最大值?

@app.route('/objects', methods = ['POST'])
def post_object():

    if 'id' in request.json and MyObject.query.get(request.json['id']) is None: #1
        object = MyObject()
        object.id = request.json['id']
    else: #2
        object = MyObject()

    object.fillFromJson(request.json)
    db.session.add(object)
    db.session.commit()
    return jsonify(object.toDict()),201

当添加一堆带有 id #1 的对象,然后尝试在没有 id 或使用已用 id #2 的情况下添加时,我得到了。

duplicate key value violates unique constraint "object_pkey"
DETAIL:  Key (id)=(2) already exists.

通常会生成 id incrementally,但如果该 id 已被使用,则不会对其进行检查。如何在自动递增和 INSERT 之间切换?

添加具有固定 ID 的对象后,您必须确保正常的增量行为不会与未来的插入发生任何冲突。

我能想到的一个可能的解决方案是将下一个插入 ID 设置为 table 中找到的最大 ID (+1)。您可以通过在代码中添加以下内容来做到这一点:

@app.route('/objects', methods = ['POST'])
def post_object():
    fixed_id = False
    if 'id' in request.json and MyObject.query.get(request.json['id']) is None: #1
        object = MyObject()
        object.id = request.json['id']
        fixed_id = True
    else: #2
        object = MyObject()

    object.fillFromJson(request.json)
    db.session.add(object)
    db.session.commit()

    if fixed_id:
        table_name = MyObject.__table__.name
        db.engine.execute("SELECT pg_catalog.setval(pg_get_serial_sequence('%s', 'id'), MAX(id)) FROM %s;" % (table_name, table_name))

    return jsonify(object.toDict()),201

下一个插入table的对象(没有固定id)将从table中找到的最大id继续id递增。