2016-09-22 73 views
0

我使用SQLAlchemy(1.1.0b3)和Postgres运行Flask应用程序。暂时禁用SQLAlchemy中的增量

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

我不想为正常操作的主键禁用“增量”选项,但如果客户端提供带有POST的ID并希望给出新的资源,则表示我想在不中断的情况下对其进行相应设置SQLAlchemy。我如何访问/重置ID的当前最大值?

@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 #2,我得到。

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

通常,ID生成incrementally但是当已经使用该ID,对没有检查。我怎么能在自动增量和INSERT之间?

+1

你有什么问题? Postgres允许您在插入过程中设置主键值。 – dirn

+0

看起来像'session.add(object)',其中'object'没有一个id为对象提供一个id,比上一次没有id时调用session.add(object)'大。 –

+0

但是,如果您有要使用的标识,那么为什么在将其添加到会话之前将其分配给该对象? – dirn

回答

0

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

我能想到的一种可能的解决方案是将下一个插入ID设置为表中找到的最大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 

下一个对象(无固定ID)将继续从表中发现的最大的ID与id增量。