def delete_discussion(session, discussion_id):
from assembl.models import (
Base, Discussion, DiscussionBoundBase, Preferences, LangStringEntry)
# delete anything related first
classes = DiscussionBoundBase._decl_class_registry.values()
classes_by_table = defaultdict(list)
for cls in classes:
if isinstance(cls, type):
classes_by_table[getattr(cls, '__table__', None)].append(cls)
# Only direct subclass of abstract
def is_concrete_class(cls):
if isabstract(cls):
return False
for (i, cls) in enumerate(cls.mro()):
if not i:
continue
if not issubclass(cls, Base):
continue
return isabstract(cls)
concrete_classes = set([cls for cls in itertools.chain(
*list(classes_by_table.values()))
if issubclass(cls, DiscussionBoundBase) and
is_concrete_class(cls)])
concrete_classes.add(Preferences)
concrete_classes.add(LangStringEntry)
tables = DiscussionBoundBase.metadata.sorted_tables
# Special case for preferences
discussion = session.query(Discussion).get(discussion_id)
session.delete(discussion.preferences)
# tables.append(Preferences.__table__)
tables.reverse()
for table in tables:
if table not in classes_by_table:
continue
for cls in classes_by_table[table]:
if cls not in concrete_classes:
continue
print('deleting', cls.__name__)
query = session.query(cls.id)
if hasattr(cls, "get_discussion_conditions"):
conds = cls.get_discussion_conditions(discussion_id)
else:
continue
assert conds
cond = and_(*conds)
v = JoinColumnsVisitor(cls, query, classes_by_table)
v.traverse(cond)
query = v.final_query().filter(cond)
if query.count():
print("*" * 20, "Not all deleted!")
ids = query.all()
for subcls in cls.mro():
if getattr(subcls, '__tablename__', None):
session.query(subcls).filter(
subcls.id.in_(ids)).delete(False)
session.flush()
评论列表
文章目录