【问题标题】:Why are some of my flask-sqlalchemy tables not setting postresql primary key to serial?为什么我的一些 flask-sqlalchemy 表没有将 postgresql 主键设置为串行?
【发布时间】:2021-12-23 18:10:04
【问题描述】:

我有一个 postgresql 数据库,里面有一些简单的表。我使用 flask-sqlalchemy 作为我的 ORM,当我对架构进行更改时,我使用 flask-migrate 进行更新。

如果我使用 DBeaver 查看我的表,我会发现我的大多数表都有一个 serial4 类型的主键。如果我使用 flask-admin 在这些表中创建新条目,它工作正常。 但是,其中两个表将主键显示为 int4,这些不会显示在烧瓶管理界面中,但是如果我尝试添加行,则会收到以下错误:

Integrity error. (psycopg2.errors.NotNullViolation) null value in column "id" of relation "priority" violates not-null constraint DETAIL: Failing row contains (P1, 4, 8, null). [SQL: INSERT INTO priority (priority, respond_by, resolve_by) VALUES (%(priority)s, %(respond_by)s, %(resolve_by)s) RETURNING priority.id] [parameters: {'priority': 'P1', 'respond_by': 4, 'resolve_by': 8}] (Background on this error at: https://sqlalche.me/e/14/gkpj)

我的模型如下所示:

# priority lookup table
class Priority(db.Model):
    __tablename__ = 'priority'
    id = db.Column(db.Integer, primary_key=True)
    priority = db.Column(db.String(2))
    respond_by = db.Column(db.Integer)  # response time in minutes e.g. created time + this many minutes
    resolve_by = db.Column(db.Integer)  # resolve in minutes as per above


class Classification(db.Model):
    __tablename__ = 'classifications'
    id = db.Column(db.Integer, primary_key=True)
    service = db.Column(db.String(50))
    category = db.Column(db.String(50))
    sub_category = db.Column(db.String(50))
    selectable = db.Column(db.Boolean())

在这两个分类表中工作正常,它创建了一个 serial4 主键。 Priority 表确实将主键创建为 int4,因此通过 flask-admin 失败。

为什么会这样?我看不出它们之间有什么区别,所以不明白为什么一个用 serial4 主键创建表而另一个没有。

【问题讨论】:

  • 附带说明:在现代 Postgres 版本 (>= 10) 中,serial 的使用是 discouraged,有利于符合标准的 identity

标签: python postgresql flask flask-admin


【解决方案1】:

感谢a_horse_with_no_name 留下的评论,我对此进行了更深入的研究并采取了平局(因为不在flask-sqlalchemy 文档中)并将db.Identity() 添加到我的主键中,如下所示:

class Priority(db.Model):
    __tablename__ = 'priority'
    id = db.Column(db.Integer, db.Identity(), primary_key=True)
    priority = db.Column(db.String(2))
    respond_by = db.Column(db.Integer) 
    resolve_by = db.Column(db.Integer)  

我对所有桌子都这样做了。但是 flask-migratee 不喜欢它,所以我删除了所有表并像这样重新创建它们(因为我使用的是蓝图)

from app import create_app, db
app = create_app()
app.app_context().push()
db.drop_all()
db.create_all()

现在查看使用 DBeaver CE 创建的表,我看到主键都是 int4(不再是串行的),如果我转到我的烧瓶管理页面 /行政 并选择任何表格,我现在可以毫无问题地创建条目。

我不知道为什么,当我之前创建没有 db.Identity() 选项的表时,有些是作为串行创建的,而另一些则不是。但是问题已经解决了,所以没有必要再纠结了。

【讨论】:

    猜你喜欢
    • 2017-08-27
    • 1970-01-01
    • 2020-03-26
    • 2010-10-24
    • 1970-01-01
    • 2020-03-04
    • 1970-01-01
    • 2017-06-25
    • 2023-03-11
    相关资源
    最近更新 更多