无法使用flask-sqlalchemy创建自动增量主键

lov*_*esh 36 python postgresql sqlalchemy flask flask-sqlalchemy

我希望我的模型的主键是一个自动递增的整数.这是我的模型的样子

class Region(db.Model):
    __tablename__ = 'regions'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(100))
    parent_id = db.Column(db.Integer, db.ForeignKey('regions.id'))
    parent = db.relationship('Region', remote_side=id, primaryjoin=('Region.parent_id==Region.id'), backref='sub-regions')
    created_at = db.Column(db.DateTime, default=db.func.now())
    deleted_at = db.Column(db.DateTime)
Run Code Online (Sandbox Code Playgroud)

上面的代码创建了我的表,但没有id自动增量.因此,如果在我的插入查询中我错过了该id字段,它会给我这个错误

错误:列"id"中的空值违反非空约束

所以我把id声明改成了这样的样子

id = db.Column(db.Integer, db.Sequence('seq_reg_id', start=1, increment=1),
               primary_key=True)
Run Code Online (Sandbox Code Playgroud)

还是一样的错误.上面的代码有什么问题?

not*_*you 33

上面的代码没有错.实际上,您甚至不需要autoincrement=True或者db.Sequence('seq_reg_id', start=1, increment=1),SQLAlchemy会自动设置第一个Integer未标记为FK的PK列autoincrement=True.

在这里,我整理了一个基于你的工作设置.如果您使用已定义的基于声明性基础的类来创建对象的实例,则SQLAlechemy的ORM将负责生成id并使用它们填充对象.

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.debug = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://user:password@localhost/testdb'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)

class Region(db.Model):
    __tablename__ = 'regions'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))

db.drop_all()
db.create_all()

region = Region(name='Over Yonder Thar')
app.logger.info(region.id) # currently None, before persistence

db.session.add(region)
db.session.commit()
app.logger.info(region.id) # gets assigned an id of 1 after being persisted

region2 = Region(name='Yet Another Up Yar')
db.session.add(region2)
db.session.commit()
app.logger.info(region2.id) # and 2

if __name__ == '__main__':
    app.run(port=9001)
Run Code Online (Sandbox Code Playgroud)

  • 我处于类似情况。假设目前表中有4条记录,从ID 1到4。当我执行db.session.query(Table_name).delete()db.session.commit()时,然后如果我执行`再次使用db.session.add()`添加新记录,下一条记录的ID为5。由于我的表现在为空,我希望新记录的ID再次从1开始。我怎样才能做到这一点 ? (2认同)
  • 这不起作用`“module_id”列中的空值违反了非空约束详细信息:失败的行包含` (2认同)
  • @qre0ct 这对于关系数据库来说实际上是没有意义的,因为您无法同时添加/删除多行。每次更改 ID 时,数据库引擎都必须检查索引是否一切正常。ID 列**不应有意义**。当然,这个规则也有一些例外。如果您担心用完 ID,只需分配“BigInt”并永远忘记它。 (2认同)

小智 9

我认为你一旦设置就不需要自动增量,

id = db.Column(db.Integer , primary_key=True , autoincrement=True)
Run Code Online (Sandbox Code Playgroud)

我觉得应该是

id = db.Column(db.Integer , primary_key=True)
Run Code Online (Sandbox Code Playgroud)

它会给你你寻找的独特性。


小智 9

所以我来到这里遇到一个问题,即我的 SQLite 表没有自动增加主键。我有一个稍微复杂的用例,我想在生产中使用 postgres,但使用 sqlite 进行测试,以便在持续部署时使生活更轻松。

事实证明,SQLite 不喜欢定义为 BigIntegers 的列,为了增加工作,它们应该设置为 Integers。值得注意的是,SQLAlchemy 可以使用 with_variant 函数按如下方式处理这种情况。认为这可能对某人有用:

id = db.Column(db.BigInteger().with_variant(db.Integer, "sqlite"), primary_key=True)
Run Code Online (Sandbox Code Playgroud)

此处有更多详细信息https://docs.sqlalchemy.org/en/13/dialects/sqlite.html

  • 我带着同样的问题登陆这里(prod=postgresql,testing=sqlite),但我的所有主键都已经是整数了。有点荒谬,但这仍然解决了它:`id = db.Column(db.Integer().with_variant(Integer, "sqlite"), Primary_key=True)` (3认同)

小智 8

我在模型类上声明复合键时遇到了这个问题。

如果您想要复合键的自动递增 id 字段(即超过 1 个db.Column(..)定义primary_key=True,那么添加autoincrement=True可以解决我的问题。

class S3Object(db.Model):
    __tablename__ = 's3_object'

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

    # composite keys
    bucket_name = db.Column(db.String(), primary_key=True)
    key = db.Column(db.String(), primary_key=True)
Run Code Online (Sandbox Code Playgroud)

所以上面关于不要求的陈述autoincrement=True应该是:

您甚至不需要autoincrement=True,因为 SQLAlchemy 会自动设置第一个未标记为 FK 的 Integer PK 列,autoincrement=True 除非您定义具有多个的复合键primary_key=True


小智 6

即使没有设置 autoincrement=True 标志,您的 id 默认情况下也会自动递增。

所以使用没有什么问题

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
Run Code Online (Sandbox Code Playgroud)

您收到的错误是由于尝试使用 id 属性填充表而导致的。您的插入查询在任何时候都不应该包含 id 属性,否则您会收到该错误。