如何在SQLAlchemy中保存计算列?

2024-04-18 22:40:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道如何在数据库中以干净的方式保存计算值:

示例(摘自SQLAlchemy手册):

Base = declarative_base()

class Interval(Base):
    __tablename__ = 'interval'

    id = Column(Integer, primary_key=True)
    start = Column(Integer)
    end = Column(Integer)

    @hybrid_property
    def length(self):
        return self.end - self.start

因此length被计算出来。但是为了更方便地查询(在另一个数据库工具中),我希望将这个length也保存到表中

因此,我的第一个粗略测试就是简单地添加:length = Column(Float)。显然,这不起作用(但我想我还是会尝试一下:p),因为length方法会覆盖length列

现在我唯一能想到的方法就是在init&;中计算它;遵从super(),如下所示:

Base = declarative_base()

class Interval(Base):
    __tablename__ = 'interval'

    id = Column(Integer, primary_key=True)
    start = Column(Integer)
    end = Column(Integer)
    length = Column(Integer)

    def __init__(self, *args, **kwargs):
        kwargs['length'] = kwargs['end'] - kwargs['start']
        super().__init__(*args, **kwargs)

然而,我觉得应该有一个更干净的方法。有吗

谢谢


Tags: 方法self数据库baseinitcolumnintegerstart
2条回答

您可以在sqlalchemy中使用column_property特性,而不是混合属性

column\u property:column\u property()函数可用于以类似于常规映射列的方式映射SQL表达式。使用此技术,在加载时将该属性与所有其他列映射属性一起加载

注意:您还可以query列的属性上

Base = declarative_base()

class Interval(Base):
    __tablename__ = 'interval'

    id = Column(Integer, primary_key=True)
    start = Column(Integer)
    end = Column(Integer)
    length = column_property(end - start)

查询示例:

session.query(Interval).filter(Interval.length == 10)

有几种方法可以解决这个问题

一种是使用^{}before_insert触发器。这是一种SQLAlchemy技术,自动检测对模型的更改,并在将行写入服务器之前调度事件。然后,您可以使用它来抢占保存,潜在地查看哪些列已更改,然后相应地更新length

另一种是使用generatedcomputed column。这些已经在[Postgres 12](generated columns)中引入,它们也出现在MySQL、Oracle和MS SQL Server中——尽管我对此知之甚少。 它们基本上做相同的事情,但您只需将该逻辑添加到表定义中,就可以随意忽略它。SQLAlchemy从1.3.11开始支持它们

相关问题 更多 >