Python 如何在SQLAlchemy中保存计算列?

Python 如何在SQLAlchemy中保存计算列?,python,sqlalchemy,Python,Sqlalchemy,我想知道如何在数据库中以干净的方式保存计算值: 示例(摘自SQLAlchemy手册): Base=declarative_Base() 课程间隔(基本): __tablename_uu='interval' id=列(整数,主键=True) 开始=列(整数) 结束=列(整数) @杂化性 def长度(自身): 返回self.end-self.start 因此,计算长度。但是为了更方便地查询(在另一个数据库工具中),我希望将这个长度也保存到表中 所以我的第一个粗略测试就是简单地添加:length=

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

示例(摘自SQLAlchemy手册):

Base=declarative_Base()
课程间隔(基本):
__tablename_uu='interval'
id=列(整数,主键=True)
开始=列(整数)
结束=列(整数)
@杂化性
def长度(自身):
返回self.end-self.start
因此,计算长度。但是为了更方便地查询(在另一个数据库工具中),我希望将这个
长度
也保存到表中

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

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

Base=declarative_Base()
课程间隔(基本):
__tablename_uu='interval'
id=列(整数,主键=True)
开始=列(整数)
结束=列(整数)
长度=列(整数)
定义初始化(self,*args,**kwargs):
kwargs['length']=kwargs['end']-kwargs['start']
super()
然而,我觉得应该有一个更干净的方法。有吗


谢谢

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

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

另一个是使用
生成的
计算列
。[Postgres 12]()中引入了这些功能,MySQL、Oracle和MS SQL Server中也有这些功能,尽管我对此知之甚少。
它们基本上做相同的事情,但您只需将该逻辑添加到表定义中,就可以随意忽略它。SQLAlchemy从开始就支持它们。

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

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

另一个是使用
生成的
计算列
。[Postgres 12]()中引入了这些功能,MySQL、Oracle和MS SQL Server中也有这些功能,尽管我对此知之甚少。 它们基本上做相同的事情,但您只需将该逻辑添加到表定义中,就可以随意忽略它。SQLAlchemy从开始就支持它们。

您可以在SQLAlchemy中使用功能,而不是混合属性

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

注意:您还可以在列属性上
查询

Base=declarative_Base()
课程间隔(基本):
__tablename_uu='interval'
id=列(整数,主键=True)
开始=列(整数)
结束=列(整数)
长度=列_属性(结束-开始)
查询示例:

session.query(Interval.filter)(Interval.length==10)
您可以使用sqlalchemy中的功能来代替混合属性

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

注意:您还可以在列属性上
查询

Base=declarative_Base()
课程间隔(基本):
__tablename_uu='interval'
id=列(整数,主键=True)
开始=列(整数)
结束=列(整数)
长度=列_属性(结束-开始)
查询示例:

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

非常感谢您的贡献,但是您描述的
length
没有保存到数据库中。非常感谢您的贡献,但是您描述的
length
没有保存到数据库中。遗憾的是,您的第二个没有工作,因为我使用的是SQLite:)。第一个给了我一个很好的暗示。我第一次尝试插入之前,但这不是很好,因为我需要的水平,以读取太多。下一个是init_标量,但在插入过程中并没有触发。所以我最终使用了“init”。修改init处理程序上的kwargs做了我需要它做的事情。我主要关心的是,它将初始化与类本身分离。所以,想想这是否真的值得一试;-)。遗憾的是,由于我使用的是SQLite:),您的第二个将无法正常工作。第一个给了我一个很好的暗示。我第一次尝试插入之前,但这不是很好,因为我需要的水平,以读取太多。下一个是init_标量,但在插入过程中并没有触发。所以我最终使用了“init”。修改init处理程序上的kwargs做了我需要它做的事情。我主要关心的是,它将初始化与类本身分离。所以,想想这是否真的值得一试;-)。