это мой декларативный код Flask-SQLAlchemy:
from sqlalchemy.ext.associationproxy import association_proxy
from my_flask_project import db
tagging = db.Table('tagging',
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id', ondelete='cascade'), primary_key=True),
db.Column('role_id', db.Integer, db.ForeignKey('role.id', ondelete='cascade'), primary_key=True)
)
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), unique=True, nullable=False)
def __init__(self, name=None):
self.name = name
@classmethod
def delete_orphans(cls):
for tag in Tag.query.outerjoin(tagging).filter(tagging.c.role_id == None):
db.session.delete(tag)
class Role(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='cascade'))
user = db.relationship('User', backref=db.backref('roles', cascade='all', lazy='dynamic'))
...
tags = db.relationship('Tag', secondary=tagging, cascade='all', backref=db.backref('roles', cascade='all'))
tag_names = association_proxy('tags', 'name')
__table_args__ = (
db.UniqueConstraint('user_id', 'check_id'),
)
В принципе, это много-много тегов с декларативным. При удалении некоторых записей из тегов я хочу, чтобы SQLAlchemy приводила в порядок сирот. Как я узнал в документах, чтобы включить эту функцию, я должен это сделать:
class Role(db.Model):
...
tags = db.relationship('Tag', secondary=tagging, cascade='all,delete-orphan', backref=db.backref('roles', cascade='all'))
...
Однако такой параметр приводит к AssertionError: этот атрибутImpl не настроен для отслеживания родителей. Я искал его и ничего не нашел, кроме раскрытого кода SQLAlchemy. Поэтому я создал classmethod Tag.delete_orphans()
(он в коде выше), чтобы называть его каждый раз, когда я думаю, что некоторые сироты могут произойти, но это не кажется очень элегантным.
Любые идеи или объяснения, почему моя настройка с помощью delete-orphan
не работает?