Python 带继承的SQLAlchemy类的一对一删除
我有一个类继承方案,如中所述 创建了Python 带继承的SQLAlchemy类的一对一删除,python,sqlalchemy,Python,Sqlalchemy,我有一个类继承方案,如中所述 创建了Child的实例后,我希望能够删除Child或Parent引用,而无需另一个挂起,但事实并非如此。当我启动IPython时 In [1]: from stackoverflow.question import Parent, Child In [2]: from sqlalchemy import create_engine In [3]: from sqlalchemy.orm import sessionmaker In [4]: session =
Child
的实例后,我希望能够删除Child
或Parent
引用,而无需另一个挂起,但事实并非如此。当我启动IPython时
In [1]: from stackoverflow.question import Parent, Child
In [2]: from sqlalchemy import create_engine
In [3]: from sqlalchemy.orm import sessionmaker
In [4]: session = sessionmaker(bind=create_engine(...), autocommit=True)()
In [5]: with session.begin():
...: session.add(Child())
...:
In [6]: session.query(Parent).all()
Out[6]: [<stackoverflow.question.Child at 0x7fe408030240>]
In [7]: session.query(Parent).delete()
---------------------------------------------------------------------------
IntegrityError Traceback (most recent call last)
/.../lib/python3.4/site-packages/sqlalchemy/engine/base.py in _execute_context(self, dialect, constructor, statement, parameters, *args)
1062 parameters,
-> 1063 context)
1064 except Exception as e:
...
--> Big traceback here...
...
IntegrityError: (IntegrityError) update or delete on table "parent" violates foreign key constraint "child_id_fkey" on table "child"
DETAIL: Key (id)=(1) is still referenced from table "child".
'DELETE FROM parent' {}
In [8]: session.query(Child).delete()
Out[8]: 1
In [9]: session.query(Parent).all()
Out[9]: [<stackoverflow.question.Child at 0x7fe408030240>]
[1]中的:从stackoverflow.question导入父项、子项
在[2]中:从sqlalchemy导入创建引擎
在[3]中:来自sqlalchemy.orm导入sessionmaker
在[4]中:session=sessionmaker(bind=create\u引擎(…),autocommit=True)()
在[5]中:使用session.begin():
…:session.add(Child())
...:
[6]中:session.query(Parent.all)()
输出[6]:[]
[7]中:session.query(Parent.delete())
---------------------------------------------------------------------------
IntegrityError回溯(最后一次调用)
/…/lib/python3.4/site-packages/sqlalchemy/engine/base.py在执行上下文中(self、方言、构造函数、语句、参数、*args)
1062个参数,
->1063(上下文)
1064例外情况除外,如e:
...
-->大回溯这里。。。
...
IntegrityError:(IntegrityError)表“parent”上的更新或删除违反了表“child”上的外键约束“child\u id\u fkey”
详细信息:键(id)=(1)仍然从表“child”引用。
'从父项删除'{}
[8]中:session.query(Child.delete())
Out[8]:1
[9]中的session.query(Parent.all)()
出[9]:[]
删除父
实例不起作用,删除子
实例会使父
实例保持活动状态
经过一点实验后,在
子中的外键中设置关键字参数ondelete='CASCADE'
,允许我删除父(它级联到子),但没有发生相反的情况。是否有任何方法可以配置这两个类,以便删除子类
也会删除父类
?我认为您会混淆一些事情
让我们暂时搁置继承
1. <代码>会话.query(MyTable).delete()
:
当您调用session.query(MyTable).delete()
时,sqlalchemy基本上将生成以下SQLdelete FROM my_table
这意味着:删除表my\u表中的所有条目
2. <代码>会话。删除(我的_实例)。。。session.commit()
执行以下操作时:
my_instance = session.query(MyTable).filter(MyTable.name == some_value).first()
session.delete(my_instance) # !!!
# ...
session.commit()
# add a child
child = Child()
session.add(child)
session.commit()
# find the Child you want to delete by its primary key
child = session.query(Child).get(child_id)
# OR: find it by other filters
child = session.query(Child).filter(...).first()
# mark it for deletion
session.delete(child)
# SA will delete all properly
session.commit()
sqlalchemy将生成以下SQL:DELETE FROM my_table,其中id=?
这意味着:针对给定的id
(主键)`,从表my\u表中删除一行
好消息是,在这种情况下,sqlalchemy足够聪明,可以在使用联接继承的情况下从多个表中删除行
(试图)回答
现在,您显示的代码基本上是第一种情况。如果您真的想删除某些表中的所有行,我认为您不关心任何引用。但我确实认为您只需要删除一个实例(可能是来自不同表的少量数据行)。在这种情况下,您只需执行以下操作:
my_instance = session.query(MyTable).filter(MyTable.name == some_value).first()
session.delete(my_instance) # !!!
# ...
session.commit()
# add a child
child = Child()
session.add(child)
session.commit()
# find the Child you want to delete by its primary key
child = session.query(Child).get(child_id)
# OR: find it by other filters
child = session.query(Child).filter(...).first()
# mark it for deletion
session.delete(child)
# SA will delete all properly
session.commit()
我想你被我格式化代码的具体方式挂断了。。。我会把它编辑得更清楚。我主要担心的是,按照你的方式做事时,仍然会有家长
对象在游荡。请先尝试一下,然后告诉我你是否仍然有这种担心。事实上,将echo=True
传递到引擎创建中,您将看到生成的SQL
语句,希望这些语句足以让您相信代码是有效的。您是对的。我没有注意到您使用了session.delete(child)
而不是query(…).delete()之类的东西。从会话中删除对象符合我的要求。在我的问题中,我正在清除表,因为这个问题是在我的单元测试的tearDown
方法中出现的,我实际上希望清除在测试期间添加的整个对象表。在这种情况下,我只需清除Parent
表即可。谢谢你消除了我的困惑!不客气。无法执行引擎。在拆卸和引擎中放置所有()
。在设置中创建所有()
?