Удаление SQLAlchemy не каскадно

Моя модель User связана с моделью Address. Я указал, что отношение должно каскадировать операцию удаления. Однако, когда я запрашиваю и удаляю пользователя, я получаю сообщение об ошибке, что на адресную строку все еще ссылаются. Как удалить пользователя и адреса?

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    addresses = db.relationship('Address', cascade='all,delete', backref='user')

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey(User.id))
db.session.query(User).filter(User.my_id==1).delete()
IntegrityError: (IntegrityError) update or delete on table "user" violates foreign key constraint "addresses_user_id_fkey" on table "address"
DETAIL:  Key (my_id)=(1) is still referenced from table "address".
 'DELETE FROM "user" WHERE "user".id = %(id_1)s' {'id_1': 1}

person AndroidDev    schedule 08.10.2013    source источник


Ответы (1)


У вас есть следующее...

db.session.query(User).filter(User.my_id==1).delete()

Обратите внимание, что после «фильтра» вам по-прежнему возвращается объект запроса. Следовательно, когда вы вызываете delete(), вы вызываете delete() для объекта Query (а не для объекта User). Это означает, что вы выполняете массовое удаление (хотя, вероятно, удаляется только одна строка)

В документации для используемого вами метода Query.delete() говорится.. .

Метод не предлагает каскадирование отношений в Python — предполагается, что ON DELETE CASCADE/SET NULL/и т. д. настроен для любых ссылок внешнего ключа, которые требуют этого, в противном случае база данных может выдать нарушение целостности, если принудительно применяются ссылки внешнего ключа.

Как говорится, запуск удаления таким образом игнорирует установленные вами каскадные правила Python. Вы, вероятно, хотели сделать что-то вроде ..

user = db.session.query(User).filter(User.my_id==1).first()
db.session.delete(user)

В противном случае вы можете посмотреть настройку также создайте каскад для вашей базы данных.

person Mark Hildreth    schedule 08.10.2013
comment
Большое спасибо. Какие изменения мне нужно внести, чтобы первый метод работал? - person AndroidDev; 08.10.2013
comment
@BadLuckBrian: это зависит от используемой вами базы данных. Прочтите документацию, на которую я ссылался в конце моего вопроса, для получения дополнительной информации. Также прочтите документацию по вашей базе данных. - person Mark Hildreth; 08.10.2013
comment
Я использую posgress на Heroku. Я добавил параметр каскада в столбец Foregien Key в таблицах Addresses. Может быть, Flask-Migrate не заметил, что это ограничение было добавлено? Могло ли это быть возможным? - person AndroidDev; 08.10.2013
comment
См. этот вопрос. Не знаком с Postgres, но, возможно, вы не можете изменить схему, чтобы добавить каскад после того, как ограничение внешнего ключа уже было создано. - person Mark Hildreth; 08.10.2013