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基本上将生成以下SQL
delete 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
表即可。谢谢你消除了我的困惑!不客气。无法执行
引擎。在
拆卸
引擎中放置所有()
。在
设置中创建所有()