无法使用 flask-sqlalchemy 创建自动递增主键
Posted
技术标签:
【中文标题】无法使用 flask-sqlalchemy 创建自动递增主键【英文标题】:unable to create autoincrementing primary key with flask-sqlalchemy 【发布时间】:2014-01-17 20:32:18 【问题描述】:我希望我的模型的主键是一个自动递增的整数。这是我的模型的样子
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)
上面的代码创建了我的表,但没有使id
自动递增。因此,如果在我的插入查询中我错过了 id
字段,它会给我这个错误
错误:“id”列中的空值违反非空约束
所以我将id
声明更改为如下所示
id = db.Column(db.Integer, db.Sequence('seq_reg_id', start=1, increment=1),
primary_key=True)
还是同样的错误。上面的代码有什么问题?
【问题讨论】:
你能贴出你用来创建区域对象的代码吗? 我正在尝试像INSERT INTO regions(name, ) ...
这样的普通sql插入
您的原始代码应该可以工作。您确定您实际上是在使用 SQLAlchemy 创建表吗?您确定您正在查看正确的数据库吗?在 SQLAlchemy 中尝试configuring logging,看看使用 SQLAlchemy 创建表时输出的 SQL 是什么。
非常好。你的代码是我的解决方案。我一直在寻找如何使用 Oracle 的序列,直到你的帖子。谢谢!
还是同样的错误
【参考方案1】:
您不能在列定义中添加“autoincrement”标志,而且在 __table__name 之后添加“__table__args”属性。 像这样的:
__tablename__ = 'table-name' __table_args__ = 'sqlite_autoincrement': True -> This adds autoincrement to your primary key.
试试吧,我希望这对你有用;)!
【讨论】:
【参考方案2】:我在模型类上声明复合键时遇到了这个问题。
如果您想要一个复合键的自动递增 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)
所以上面关于不需要autoincrement=True
的陈述应该是:
你甚至不需要
autoincrement=True
,因为 SQLAlchemy 会自动设置第一个 未将 FK 标记为autoincrement=True
的整数 PK 列除非您定义的复合键包含多个primary_key=True
【讨论】:
【参考方案3】:即使没有设置 autoincrement=True 标志,默认情况下您的 id 也会自动递增。
所以使用没有什么问题
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
您遇到的错误是由于尝试使用 id 属性填充表。您的插入查询在任何时候都不应包含 id 属性,否则您将收到该错误。
【讨论】:
【参考方案4】:即使添加了autoincrement=True
,我也遇到了同样的错误。
问题是我已经创建了迁移。所以我降级到之前的迁移,删除迁移,重新创建迁移并升级。
然后错误就消失了。
希望它可以帮助坚持这一点的人。
结束:添加autoincrement=True
,并确保您的迁移得到更新和应用。
【讨论】:
【参考方案5】:所以我遇到了一个问题,即我的 SQLite 表没有自动递增主键。我有一个稍微复杂的用例,我想在生产中使用 postgres,但使用 sqlite 进行测试,以便在持续部署时让生活更轻松。
事实证明 SQLite 不喜欢定义为 BigIntegers 的列,并且为了递增工作,它们应该设置为 Integers。值得注意的是,SQLAlchemy 可以使用 with_variant 函数按如下方式处理这种情况。认为这可能对某人有用:
id = db.Column(db.BigInteger().with_variant(db.Integer, "sqlite"), primary_key=True)
更多详情在这里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)
这是解决我的问题的最佳答案(postgresql->production,sqlite->test)。谢谢【参考方案6】:
我认为你一旦设置就不需要自动增量,
id = db.Column(db.Integer , primary_key=True , autoincrement=True)
我认为应该是,
id = db.Column(db.Integer , primary_key=True)
它将为您提供您所寻找的独特性。
【讨论】:
【参考方案7】:上面的代码没有错。实际上,您甚至不需要autoincrement=True
或db.Sequence('seq_reg_id', start=1, increment=1),
,因为SQLAlchemy 会自动将第一个未标记为FK 的Integer
PK 列设置为autoincrement=True
。
在这里,我根据您的设置整理了一个工作设置。 SQLAlechemy 的 ORM 将负责生成 id 并用它们填充对象如果您使用您定义的基于 Declarative Base 的类来创建对象的实例。
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)
【讨论】:
我也有类似的情况。假设现在表中有 4 条记录,从 id 1 到 4。当我执行db.session.query(Table_name).delete() db.session.commit()
然后如果我再次执行 db.session.add()
以添加新记录,下一条记录的 id 为 5。因为我的表现在是空的,我希望我的新记录现在再次从 1 开始获得一个 id。我该怎么做?
我试图找出一个不同但相关的问题,即如何根据 model.py 填充我的数据库,并发现 db.drop_all()
和 db.create_all()
是超级有帮助。谢谢。
这也适用于 Oracle 数据库,您必须在其中安装/设置一个序列来处理 AUTOINCREMENT 主键处理。
这不起作用`“module_id”列中的空值违反了非空约束细节:失败的行包含`
@qre0ct 这对于关系数据库实际上毫无意义,因为您将无法同时添加/删除多行。每次更改 ID 时,您的数据库引擎都必须检查您的索引是否一切正常。 ID 列应该没有意义。当然,这条规则也有一些例外。如果您担心 ID 用完,只需分配 BigInt
并永远忘记它。以上是关于无法使用 flask-sqlalchemy 创建自动递增主键的主要内容,如果未能解决你的问题,请参考以下文章
使用 Flask-SQLAlchemy 在 Alembic 自动生成迁移中未检测到任何变化
AttributeError:使用flask-sqlalchemy连接到sqlite数据库时无法设置属性