在我的项目(由SQLAlChemy创建和管理的Postgres数据库)中,我使用MappdAsDataclass和DeclarativeBase创建如下表:

class Base(MappedAsDataclass, DeclarativeBase):
    """subclasses will be converted to dataclasses"""

class Collection(Base):
    __tablename__ = 'collections'
    collection_id: Mapped[int] = mapped_column(init=False, primary_key=True)
    collection_name: Mapped[str] = mapped_column(default=None, unique = True)

User.__table__

Collection.metadata.create_all(engine)

我想用一个计算列‘ezname’创建这个表,该列从‘Collection_name’中的条目中删除空格,并用‘_’下划线替换它们.

我可以通过创建上面的表,然后运行原始的postgres命令来获得我想要的:

ALTER TABLE collections ADD column ezname varchar GENERATED ALWAYS AS (REGEXP_REPLACE(collection_name, ' ', '_')) stored;

有没有办法在ORM模型中创建此列,特别是在使用MappdAsDataclass和DeclarativeBase声明表时?

在我阅读文档的过程中,我遇到了@hybrid_propertycolumn_property,然而,到目前为止,我试图让它们使用我映射的数据类模式的try 都失败了.

我一直在try 这样的东西(显然不起作用)

class Collection(Base):
    __tablename__ = 'collections'
    collection_id: Mapped[int] = mapped_column(init=False, primary_key=True)
    collection_name: Mapped[str] = mapped_column(default=None, unique = True)
    collection_ezname: Mapped[str] = mapped_column(default=None, unique = True, Computed(REGEXP_REPLACE(collection_name, ' ', '_')))

因此,首先我想知道SQLA是否可以做到这一点,如果可以,如何做到这一点?

请注意,对于我来说,重要的是逻辑在创建后成为表本身的一部分,因此可以移植到ORM上下文之外.

推荐答案

你差一点就成功了,你可以用这个.

from sqlalchemy import Computed, create_engine, func, select
from sqlalchemy.orm import Mapped, MappedAsDataclass, DeclarativeBase, Session, mapped_column

class Base(MappedAsDataclass, DeclarativeBase):
    pass

class Collection(Base):
    __tablename__ = 'collections'
    collection_id: Mapped[int] = mapped_column(init=False, primary_key=True)
    collection_name: Mapped[str] = mapped_column(default=None, unique=True)
    collection_ezname: Mapped[str] = mapped_column(Computed(func.REGEXP_REPLACE(collection_name, ' ', '_')), unique=True, init=False)

engine = create_engine("")

Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)

with Session(engine) as session:
    session.add(Collection('something with space'))
    session.commit()

with Session(engine) as session:
    for i in session.scalars(select(Collection)):
        print(i)

这将生成以下内容

CREATE TABLE collections (
        collection_id SERIAL NOT NULL, 
        collection_name VARCHAR NOT NULL, 
        collection_ezname VARCHAR GENERATED ALWAYS AS (REGEXP_REPLACE(collection_name, ' ', '_')) STORED NOT NULL, 
        PRIMARY KEY (collection_id), 
        UNIQUE (collection_name), 
        UNIQUE (collection_ezname)
)

输出

Collection(collection_id=1, collection_name='something with space', collection_ezname='something_with space')

You may have to change your regex as it currently does not replace multiple spaces and other scenarios I can't think of. Probably 100?

Postgresql相关问答推荐

如何在postquist中修剪第一/后文件名

如何在Common Lisp中使用Postmodern在表更改时获得通知?

从数据集中提取彼此喜欢的用户(&Q;)

如何在Postgres中对分区表使用Hibernate验证?

supabase 中的交易

我想优化查询SQL

如何防止 PDO 将问号解释为占位符?

postgres 的密码

处理 sqlalchemy 断开连接的更好方法

在 to_tsquery 中转义特殊字符

在执行 postgresql 函数时提交事务

org.postgresql.util.PSQLException:错误:relation "app_user" does not exist

MAC OS X 上的 Postgres 权限被拒绝

是否可以在 PostgreSQL 中部分刷新materialized视图?

PostgreSQL CASE 在函数中的使用

丢弃顺序和级联

在 PostgreSQL 中的表上禁用 DELETE?

Django:按月查询组

调用 getNextException 来查看原因:如何让 Hibernate / JPA 显示异常的数据库服务器消息

pg_restore 目录错误