Как определить ForeignKey и отношение таким образом, чтобы можно было отключить поведение FK-обнуления SQLAlchemy?Документация здесь , кажется, описывает использование passive_deletes=True
, чтобы разрешить каскадное удаление базы данных, но только в контексте определения свойства отношения cascade
, задокументированного здесь , свойствакоторый, как мне кажется, определяет, как SQLAlchemy будет выполнять само каскадное удаление, , которое явно описывается как более медленное, чем каскадное удаление ядра СУБД в этом разделе (см. зеленое поле с названием Каскад «удаления» на уровне ORM против уровня «ВНЕШНИЙ КЛЮЧ» Каскад «ON DELETE» ).
Чтобы использовать каскадное удаление базы данных, мы должны сделать следующее?
- определить
ondelete="CASCADE"
в столбце ForeignKey
, - определить
passive_deletes=True
в тех же отношениях, - И определить
cascade="delete, delete-orphan"
параметр для всех отношений между объектами?
Это шаг 3, который, по-моему, смущен: похоже, он определяет каскад для SQLAlchemy, а не разрешает базы данныхе выполнить собственное удаление.Но SQLAlchemy, похоже, хочет обнулить все зависимые внешние ключи до , когда база данных может получить возможность каскадного удаления.Мне нужно отключить это поведение, но passive_deletes=True
, кажется, не делает это самостоятельно.
(поздний) ответ здесь явно решает мою проблему, но она не работает.Он заявляет:
Здесь есть важное предупреждение.Обратите внимание, как у меня есть отношения, указанные с passive_deletes=True
?Если у вас этого нет, все это не будет работать.Это потому, что по умолчанию при удалении родительской записи SqlAlchemy делает что-то действительно странное.Он устанавливает внешние ключи всех дочерних строк в NULL
.Таким образом, если вы удалите строку из parent_table
, где id = 5
, то она в основном будет выполняться UPDATE child_table SET parent_id = NULL WHERE parent_id = 5
В моем коде
class Annotation(SearchableMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
locked = db.Column(db.Boolean, index=True, default=False)
active = db.Column(db.Boolean, default=True)
HEAD = db.relationship("Edit",
primaryjoin="and_(Edit.current==True,"
"Edit.annotation_id==Annotation.id)", uselist=False,
lazy="joined", passive_deletes=True)
edits = db.relationship("Edit",
primaryjoin="and_(Edit.annotation_id==Annotation.id,"
"Edit.approved==True)", lazy="joined", passive_deletes=True)
history = db.relationship("Edit",
primaryjoin="and_(Edit.annotation_id==Annotation.id,"
"Edit.approved==True)", lazy="dynamic", passive_deletes=True)
all_edits = db.relationship("Edit",
primaryjoin="Edit.annotation_id==Annotation.id", lazy="dynamic",
passive_deletes=True)
class Edit(db.Model):
id = db.Column(db.Integer, primary_key=True)
edit_num = db.Column(db.Integer, default=0)
approved = db.Column(db.Boolean, default=False, index=True)
rejected = db.Column(db.Boolean, default=False, index=True)
annotation_id = db.Column(db.Integer,
db.ForeignKey("annotation.id", ondelete="CASCADE"), index=True)
hash_id = db.Column(db.String(40), index=True)
current = db.Column(db.Boolean, default=False, index=True, passive_deletes=True)
annotation = db.relationship("Annotation", foreign_keys=[annotation_id])
previous = db.relationship("Edit",
primaryjoin="and_(remote(Edit.annotation_id)==foreign(Edit.annotation_id),"
"remote(Edit.edit_num)==foreign(Edit.edit_num-1))")
priors = db.relationship("Edit",
primaryjoin="and_(remote(Edit.annotation_id)==foreign(Edit.annotation_id),"
"remote(Edit.edit_num)<=foreign(Edit.edit_num-1))",
uselist=True, passive_deletes=True)
просто установите passive_deletes=True
родительские отношения не работают .Я также подумал, что, возможно, это вызвано отношениями ребенка с его братьями и сестрами (отношения Edit.previous
и Edit.priors
), но установка passive_deletes=True
для этих двух отношений не решает проблему, иэто вызывает следующие предупреждения, когда я просто запускаю Edit.query.get(n)
:
/ home / malan / projects / icc / icc / venv / lib / python3.7 / site-packages / sqlalchemy / orm /Relationss.py:1790: SAWarning: В Edit.previous «passive_deletes» обычно настраивается только для отношений «один ко многим», «один к одному», «многие ко многим».% self)
/ home / malan / projects / icc / icc / venv / lib / python3.7 / site-packages / sqlalchemy / orm / relationss.py: 1790: SAWarning: On Edit.priors, 'passive_deletes 'обычно настраивается только на отношения «один ко многим», «один к одному», «многие ко многим».% self)
На самом деле я нашел этот интересный вопрос 2015 года, на который никогда не было ответа.В ней подробно описана неудачная попытка выполнить код документации.