postgresql 无法使用flank-sqlalchemy创建自动递增主键

7kjnsjlb  于 2022-12-03  发布在  PostgreSQL
关注(0)|答案(9)|浏览(267)

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

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 = db.Column(db.Integer, db.Sequence('seq_reg_id', start=1, increment=1),
               primary_key=True)

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

31moq8wy

31moq8wy1#

上面的代码没有任何问题。实际上,您甚至不需要autoincrement=Truedb.Sequence('seq_reg_id', start=1, increment=1),,因为SQLAlchemy会自动将第一个没有标记为FK的Integer PK列设置为autoincrement=True
在这里,我已经根据您的设置整理了一个工作设置。SQLAlechemy的ORM将负责生成id并用它们填充对象 *,如果您使用基于声明性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)
eanckbw9

eanckbw92#

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

vm0i2vca

vm0i2vca3#

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

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

我认为应该是这样,

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

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

g9icjywg

g9icjywg4#

我在模型类上声明组合键时遇到了这个问题。
如果你想要一个组合键的自动递增的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的Integer PK列设置为autoincrement=True,除非您定义的组合键具有多个primary_key=True

vecaoik1

vecaoik15#

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

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

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

wgx48brx

wgx48brx6#

我有同样的错误,即使在添加autoincrement=True
问题是我已经创建了迁移。所以我降级到以前的迁移,删除迁移,再次创建迁移并升级。
然后错误就消失了。
希望能对被困在这上面的人有所帮助。
绕线:添加autoincrement=True,并确保更新并应用迁移。

e4eetjau

e4eetjau7#

不能在列定义中添加“自动增量”标志,而且不能在__table__name后面添加“__table__args”属性。如下所示:

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

试试吧,我希望这对你有用;)!

o4hqfura

o4hqfura8#

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

iyfjxgzm

iyfjxgzm9#

试试这个代码,它对我很有效。
__init__函数内不要指定id,所以当你创建一个新的“User”对象时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='another_admin@mail.com')
guest = User(username = 'another guest', email='another_guest@mail.com')

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

with app.app_context():
    db.session.add(admin)
    db.session.add(guest)
    db.session.commit()

相关问题