Python Sqlalchemy post_关系更新似乎对我不起作用

Python Sqlalchemy post_关系更新似乎对我不起作用,python,sqlalchemy,flask-sqlalchemy,Python,Sqlalchemy,Flask Sqlalchemy,我有两个模型(sqlalchemy 0.9),它们相互引用(简化并使用整数作为id) 我需要这样做: device = Device() device.id = 1 program = Program() program.id = 2 program.device_id = device.id device.current_program_id = program.id db.session.add_all([device, program,]) db.session.commit() 但我得

我有两个模型(sqlalchemy 0.9),它们相互引用(简化并使用整数作为id)

我需要这样做:

device = Device()
device.id = 1
program = Program()
program.id = 2
program.device_id = device.id
device.current_program_id = program.id
db.session.add_all([device, program,])
db.session.commit()
但我得到了:

IntegrityError: (IntegrityError) (1452, 'Cannot add or update a child row: a foreign key constraint fails (`cloud2`.`devices`, CONSTRAINT `fk_current_program` FOREIGN KEY (`current_program_id`) REFERENCES `programs` (`id`))') 'UPDATE devices SET created=%s, updated=%s, name=%s, rain_detected=%s, current_program_id=%s, timezone=%s, synced=%s WHERE devices.id = %s' (datetime.datetime(2015, 8, 11, 19, 48, 23), datetime.datetime(2015, 8, 11, 19, 48, 26), 'nWhosie', 0, '\xeaL\xff\x80\xe5\xffC2\x9a)\xe5\x86\xe4\xad}l', 'America/Chicago', datetime.datetime(2015, 8, 11, 19, 48, 27), '\xd4\xe3\x04;:\xa0M\xce\x95\x9a\xf9U\x05x"\x10')
注意:我在real中使用的不是int-id

我认为使用post_update=True,它将按预期工作。我做错了什么

谢谢

更新 正如@gsb eng提到的,问题的根源应该是缺少显式关系设置。但这是一个问题,因为对象是从dict列表生成的,很难找出所有关系

更新2 最后,我在inspect的帮助下修复了关系:

def fix_relationships(objs):
    for obj in objs:
        insp = inspect(type(obj))
        for relation in insp.relationships:
            if relation.post_update:
                # A relation to be set
                relation_key = relation.key
                if getattr(obj, relation_key):
                    # Relation had already been set
                    continue
                foreign_key = relation.primaryjoin.left.key
                target_class_name = relation.argument.arg
                target_key = relation.primaryjoin.right.key
                fk = getattr(obj, foreign_key)
                if not fk:
                    # Nothing to set.
                    continue
                for o in objs:
                    if o.__class__.__name__ == target_class_name \
                            and getattr(o, target_key) == fk:
                        setattr(obj, relation_key, o)
                        setattr(obj, foreign_key, None)
                        break

正如我在下面观察到的错误,它试图为我们的程序
当前\u程序\u id='\xeaL\xff\x80\xe5\xffC2\x9a)\xe5\x86\xe4\xad}l'
插入此值,该值应该是它定义的整数值

UPDATE devices SET created=%s, updated=%s, name=%s, rain_detected=%s, current_program_id=%s, timezone=%s, synced=%s WHERE devices.id = %s' (datetime.datetime(2015, 8, 11, 19, 48, 23), datetime.datetime(2015, 8, 11, 19, 48, 26), 'nWhosie', 0, '\xeaL\xff\x80\xe5\xffC2\x9a)\xe5\x86\xe4\xad}l', 'America/Chicago', datetime.datetime(2015, 8, 11, 19, 48, 27), '\xd4\xe3\x04;:\xa0M\xce\x95\x9a\xf9U\x05x"\x10')
理想情况下,它不应该触发
UPDATE
查询,因为您没有提到关系,
device.current\u program=program
定义了这两个对象之间的实际关系。您最好尝试运行此

device = Device()
device.id = 1
program = Program()
program.id = 2
device.current_program = program
device.programs = [program]
db.session.add_all([device, program,])
db.session.commit()

正如我在下面观察到的错误,它试图为我们的程序
当前\u程序\u id='\xeaL\xff\x80\xe5\xffC2\x9a)\xe5\x86\xe4\xad}l'
插入此值,该值应该是它定义的整数值

UPDATE devices SET created=%s, updated=%s, name=%s, rain_detected=%s, current_program_id=%s, timezone=%s, synced=%s WHERE devices.id = %s' (datetime.datetime(2015, 8, 11, 19, 48, 23), datetime.datetime(2015, 8, 11, 19, 48, 26), 'nWhosie', 0, '\xeaL\xff\x80\xe5\xffC2\x9a)\xe5\x86\xe4\xad}l', 'America/Chicago', datetime.datetime(2015, 8, 11, 19, 48, 27), '\xd4\xe3\x04;:\xa0M\xce\x95\x9a\xf9U\x05x"\x10')
理想情况下,它不应该触发
UPDATE
查询,因为您没有提到关系,
device.current\u program=program
定义了这两个对象之间的实际关系。您最好尝试运行此

device = Device()
device.id = 1
program = Program()
program.id = 2
device.current_program = program
device.programs = [program]
db.session.add_all([device, program,])
db.session.commit()

您正在使用哪个数据库?对于Python 3.8和SQLAlchemy 1.3似乎毫无例外。您正在使用哪个数据库?对于Python 3.8和SQLAlchemy 1.3似乎毫无例外。>这应该是定义的整数值-是的,我使用的不是整数ID。我显示的代码是简化的,因为您没有提到关系,device.current_program=program-有意义。问题是,在抽象算法中,对象是从一长串dict生成的,我只能设置id。有办法吗?我的意思是让更新后的工作没有提到relationship@SerafimSuhenky
post_update
背后的意图是解决这种
双向关系,您必须定义
关系
,然后只有
SqlALchemy
Insert
delete
发生之前才执行正确的
update
。谢谢,在您的帮助下,我终于解决了我的问题。值得一提的是:如果您同时设置了关系和外键,post_update将不会触发>这应该是它定义的整数值-是的,我使用的不是整数ID。我显示的代码是简化的,因为您没有提到关系,device.current_program=program-有意义。问题是,在抽象算法中,对象是从一长串dict生成的,我只能设置id。有办法吗?我的意思是让更新后的工作没有提到relationship@SerafimSuhenky
post_update
背后的意图是解决这种
双向关系,您必须定义
关系
,然后只有
SqlALchemy
Insert
delete
发生之前才执行正确的
update
。谢谢,在您的帮助下,我终于解决了我的问题。值得一提的是:如果您同时设置了关系和外键,post_更新将不会启动