我如何将Flask-SQLAlchemy与Postgres结合使用,让主键不重复使用已删除的数字?

时间:2020-07-03 22:13:13

标签: python sqlalchemy flask-sqlalchemy

我在Flask-SQLAlchemy和Postgres中使用。我注意到,当我删除一条记录时,下一条记录将重复使用该ID,这对我而言并不理想。另一个SO问题是这是默认行为。特别是,他的SO question讨论了后台的sql。但是,当我在此问题中测试解决方案时,它不起作用。实际上,postgres并未使用SERIAL作为主键。我本人必须在pgadmin中进行编辑。其他程序中的解决方案提到使用Sequence,但未显示序列的来源。

所以我希望这段代码:


class Test1(db.Model):
    __tablename__ = "test1"

    # id = ... this is what needs to change
    id = db.Column(db.Integer, primary_key=True)

如果记录3被删除而另一个像这样创建,则不会重复使用说3:

i1 = Invoice()
db.session.add(i1)
i2 = Invoice()
db.session.add(i2)
i3 = Invoice()
db.session.add(i3)
db.session.commit()

invs = Invoice.query.all()
for i in invs:
    print(i.id)  # Should print 1,2,3

Invoice.query.filter(id=3).delete()  # no 3 now
db.session.commit()

i4 = Invoice()
db.session.add(i4)
db.session.commit()

invs = Invoice.query.all()
for i in invs:
    print(i.id)  # Should print 1,2,4

其他,解决方案据说使用autoincrement=False。好的,但是那我该如何确定将ID设置为什么数字呢?有没有一种方法可以将变量保存为类而不将其作为列:

class Test2(db.Model)
    __tablename__ = 'test2'

    id = ...
    last_id = 3

    # code to set last_id when a record is deleted

编辑: 因此,我可以(尽管我不认为应该)使用Python来做到这一点。我认为这更清楚地试图说明我要做什么。

class Test1(db.Model):
    __tablename__ = "test1"

    # id = ... this is what needs to change
    id = db.Column(db.Integer, primary_key=True) 
    last_used_id = 30

    def __init__(self):
        self.id = last_used_id + 1
        self.last_used_id +=1

# Not sure if this somehow messes with SQLAlchemy / the db making the id first.

这将使任何新记录都不会触摸已使用的ID。 但是,通过这种方法,我确实遇到了Python的类变量问题。参见this SO question


未来的自检:请参见每个@net评论here的UUID:

1 个答案:

答案 0 :(得分:0)

您应该使用autoincrement=True。每当您添加新行时,这都会自动增加ID。

class Test1(db.Model):
    __tablename__ = "test1"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True, unique=True, nullable=False)
    ....

由于性能问题,默认情况下Postgres不会重用ID。尝试避免间隔或重新使用已删除的ID会造成可怕的性能问题。参见PostgreSQL wiki FAQ

您无需跟踪ID。当您调用db.session.add(i4)db.session.commit()时,它将自动插入ID递增的