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

问题描述 投票:0回答:10

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

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)

还是同样的错误。上面的代码有什么问题吗?

python postgresql sqlalchemy flask flask-sqlalchemy
10个回答
78
投票

上面的代码没有任何问题。事实上,您甚至不需要

autoincrement=True
db.Sequence('seq_reg_id', start=1, increment=1),
,因为 SQLAlchemy 会自动将未标记为 FK 的第一个
Integer
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)

18
投票

所以我遇到了一个问题,我的 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


13
投票

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

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

我觉得应该是这样,

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

它将给您带来您所寻找的独特性。


8
投票

我在模型类上声明 Composite Keys 时遇到了这个问题。

如果您想要复合键的自动递增 id 字段(即使用

db.Column(..)
定义超过 1 个
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 的整数 PK 列为
autoincrement=True
除非您定义具有多个
primary_key=True

的复合键

5
投票

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

所以使用没有什么问题

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

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


3
投票

即使添加了

autoincrement=True
之后,我也遇到了同样的错误。

问题是我已经创建了迁移。所以我降级到之前的迁移,删除迁移,再次创建迁移并升级。

然后错误就消失了。

希望它能帮助那些陷入困境的人。

结束:添加

autoincrement=True
,并确保您的迁移已更新并应用。


1
投票

不能在列定义中添加“自动增量”标志,而且不能在 __table__name 后面添加“__table__args”属性。 像这样的东西:

    __tablename__ = 'table-name'
    __table_args__ = {'sqlite_autoincrement': True} -> This adds autoincrement to your primary key.

尝试一下,我希望这对你有用;)!


0
投票

我发现的方法是: def init(自我): 是阻碍自动递增的罪魁祸首,当我将其注释掉时,它起作用了。 用 postgres 和 mysql 尝试过


-1
投票

在我的例子中,我只是添加了 id 作为外部参数,而不依赖于 sqlalchemy


-1
投票

尝试一下这个代码,它对我有用。

__init__
函数中不要指定id,因此当您创建新的“用户”对象时,SQLAlchemy将自动为您生成唯一的id号。

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.sqlite3'
app.config['SQLAlCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

class User(db.Model):
    _id = db.Column(db.Integer, primary_key = True, autoincrement = True)
    username = db.Column(db.String(80), unique = True, nullable = False)
    email = db.Column(db.String(120), unique = True, nullable = False)

def __init__(self, username, email):
    self.username = username
    self.email = email

这行代码将在数据库中创建我们想要的表。

with app.app_context():
    db.create_all()


admin = User(username = 'another admin', email='[email protected]')
guest = User(username = 'another guest', email='[email protected]')

下面的代码会将我们的数据推送到表中。

with app.app_context():
    db.session.add(admin)
    db.session.add(guest)
    db.session.commit()
© www.soinside.com 2019 - 2024. All rights reserved.