I am defining a mapped class using sqlalchemy. It contains three user defined values (a,b,c) and one dependend value (abc), which is calculated using a, b and c.
I want to attach a listener to a, b and c, which updates abc, when their values are changed.
Using event.listen(variable.a, 'set', updateFunction) calls the function, which should update abc. Unfortunately the event is fired before the new value is stored in the variable. Therefore abc will be calculated using the old values.
Example:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, Numeric, Sequence
from sqlalchemy import event
base = declarative_base()
class demo(base):
__tablename__ = 'demo'
id = Column(Integer, Sequence('some_id_seq'), primary_key=True)
a = Column(Integer)
b = Column(Integer)
c = Column(Integer)
abc = Column(Numeric) #calculated from a, b, and c
def __init__(self, A, B, C):
self.a = A
self.b = B
self.c = C
self.calcABC() #initial calculation of abc
event.listen(demo.a, 'set', self.calcABCEvent, named=True)
event.listen(demo.b, 'set', self.calcABCEvent, named=True)
event.listen(demo.c, 'set', self.calcABCEvent, named=True)
#super complicated formular
def calcABC(self):
self.abc = ( self.a + self.b ) * self.c
#This event ist called, before the new value is set
#Thus the calculation is not correct
def calcABCEvent(self, target, value, oldvalue, initiator):
print("\nevent called")
print(f"self.a \t\t{self.a}")
print(f"target.a \t{target.a}")
print(f"oldvalue \t{oldvalue}")
print(f"value \t\t{value}") #The new value only appears in value
self.calcABC()
def __str__(self):
return f"({self.a} + {self.b}) * {self.c} = {self.abc}"
print("init")
obj = demo(1,2,3)
print(obj) #abc should be (1+2)*3 = 9
print("\nchange a to 4")
obj.a = 4
print("\nchanged object")
print(obj) #abc should be (4+2)*3 = 18
Output:
init
(1 + 2) * 3 = 9
change a to 4
event called
self.a 1
target.a 1
oldvalue 1
value 4
changed object
(4 + 2) * 3 = 9
How can i update abc using only one function? In my application, abc is calculated using seven variables, and i want to avoid writing seven update functions. Is there something like event.listen(variable.a, 'after_set', updateFunction)?