Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在sqlalchemy中删除所有子对象后删除父对象_Python_Orm_Sqlalchemy_Associations_Relationship - Fatal编程技术网

Python 在sqlalchemy中删除所有子对象后删除父对象

Python 在sqlalchemy中删除所有子对象后删除父对象,python,orm,sqlalchemy,associations,relationship,Python,Orm,Sqlalchemy,Associations,Relationship,假设我有以下关系: Reference(幻灯片id,组id)其中Reference是幻灯片和组的关联 一张幻灯片可用于多个参考资料(不同的组):主键是slide\u id+group\u id,必须是唯一的 我想在删除指向的组或幻灯片时删除所有引用。 我通过在关系的backref中添加级联来实现: # definition of Reference model slide = db.relationship( Slide, backref=db.backref('referen

假设我有以下关系:

Reference(幻灯片id,组id)
其中Reference是幻灯片和组的关联

一张幻灯片可用于多个参考资料(不同的组):主键是
slide\u id
+
group\u id
,必须是唯一的

我想在删除指向的组或幻灯片时删除所有引用。 我通过在关系的backref中添加级联来实现:

# definition of Reference model

slide = db.relationship(
    Slide,
    backref=db.backref('references', cascade='all, delete, delete-orphan')
)

group = db.relationship(
    Group,
    backref=db.backref('references', cascade='all, delete, delete-orphan')
)
我还希望删除引用的组或幻灯片,只要我删除了引用,并且没有其他引用使用了所述组和/或幻灯片

我考虑过使用
@listens\u for(Reference,'after\u delete')
在需要时手动删除家长。我也尝试过在关系中使用属性组合,但我不确定如何解决这个问题。

我认为使用属性组合的想法不错。您只需收听
参考
。下面是一个有帮助的例子

class Slide(db.Model):
    __tablename__ = 'slide'

    id = db.Column(db.Integer, primary_key=True)
    children = db.relationship('Reference')
    references = db.relationship('Reference', back_populates='slide')


class Group(db.Model):
    __tablename__ = 'group'

    id = db.Column(db.Integer, primary_key=True)
    references = db.relationship('Reference', back_populates='group')


class Reference(db.Model):
    __tablename__ = 'reference'

    id = db.Column(db.Integer, primary_key=True)
    slide_id = db.Column(db.Integer, db.ForeignKey('slide.id'))
    group_id = db.Column(db.Integer, db.ForeignKey('group.id'))
    group = db.relationship('Group', back_populates='references')
    slide = db.relationship('Slide', back_populates='references')


@event.listens_for(Reference, 'before_delete')
def delete_reference(mapper, connection, target):
    # after_flush used for consistent results
    @event.listens_for(Session, 'after_flush', once=True)
    def receive_after_flush(session, context):
        # just do here everything what you need...
        # if our preference slide is the last one
        if target.slide and not target.slide.references:
            print('add slide with id = %s to delete' % target.slide.id)
            session.delete(target.slide)
        # if our preference group is the last one
        if target.group and not target.group.references:
            session.delete(target.group)
            print('add group with id = %s to delete' % target.group.id)
让我们检查一下:

# clear tables
Reference.query.delete()
Group.query.delete()
Slide.query.delete()
# create one reference with only 1 group and only 1 slide
reference = Reference(group=Group(), slide=Slide())
db.session.add(reference)
db.session.commit()

print('reference with id %s was created. slide_id = %s, group_id = %s' % (
    reference.id, reference.slide_id, reference.group_id
))
reference = Reference.query.filter_by(id=reference.id).first()
print('add reference with id = %s to delete' % reference.id)
db.session.delete(reference)
db.session.commit()
print('amount references after delete: %s' % Reference.query.all())


# create 2 references but with the same group and slide
group = Group()
slide = Slide()
reference = Reference(group=group, slide=slide)
reference2 = Reference(group=group, slide=slide)
db.session.add(reference)
db.session.add(reference2)
db.session.commit()
print('reference with id %s was created. slide_id = %s, group_id = %s' % (
    reference.id, reference.slide_id, reference.group_id
))
print('reference2 with id %s was created. slide_id = %s, group_id = %s' % (
    reference2.id, reference2.slide_id, reference2.group_id
))

reference = Reference.query.filter_by(id=reference.id).first()
print('add reference with id = %s to delete' % reference.id)
db.session.delete(reference)
print('amount references after delete: %s' % Reference.query.all())
db.session.commit()
您将看到,在第一种情况下,
首选项
幻灯片
被删除。因为其他
首选项
幻灯片
无关。但在第二种情况下,您将看到只有
首选项
被删除:

reference with id 76 was created. slide_id = 65, group_id = 65
add reference with id = 76 to delete
add slide with id = 65 to delete
add group with id = 65 to delete
amount references after delete: []
reference with id 77 was created. slide_id = 66, group_id = 66
reference2 with id 78 was created. slide_id = 66, group_id = 66
add reference with id = 77 to delete
# with slide_id = 66, group_id = 66
amount references after delete: [<Reference 78>]
已创建id为76的引用。幻灯片id=65,组id=65 添加id=76的引用以删除 添加id=65的幻灯片以删除 添加id=65的组以删除 删除后的金额参考:[] 已创建id为77的引用。幻灯片id=66,组id=66 已创建id为78的引用2。幻灯片id=66,组id=66 添加id=77的引用以删除 #幻灯片id=66时,组id=66 删除后的金额参考:[]
希望这有帮助