PCv5/app/models/thread.py
Lephe 3c5599adf7
model: avoid the foreign key cycle between Thread and Comment
By specifying use_alter=True on one of the keys, the ORM will generate
an ALTER command to set the second foreign key after inserting both
objects, in case two new objects referring to each other have to be
created.

See: https://docs.sqlalchemy.org/en/14/core/exceptions.html#sqlalchemy.exc.CircularDependencyError
2021-07-07 19:38:28 +02:00

71 lines
2.2 KiB
Python

from app import db
class Thread(db.Model):
"""Some thread, such as a topic, program, tutorial."""
__tablename__ = 'thread'
# Unique ID
id = db.Column(db.Integer, primary_key=True)
# Top comment
top_comment_id = db.Column(db.Integer,
db.ForeignKey('comment.id', use_alter=True))
top_comment = db.relationship('Comment', foreign_keys=top_comment_id)
# Post owning the thread, set only by Topic, Program, etc. In general, you
# should use [owner_post] which groups them together.
owner_topic = db.relationship('Topic')
owner_program = db.relationship('Program')
# Other fields populated automatically through relations:
# <comments> The list of comments (of type Comment)
COMMENTS_PER_PAGE = 20
def __init__(self):
"""
Create a empty Thread. Normally threads are not meant to be empty, so
you should create a Comment with this thread as parent, then assign it
as top comment with a call to set_top_comment().
"""
self.top_comment_id = None
def set_top_comment(self, top_comment):
"""
Changes the top comment of the thread. The old top comment will usually
become visible in the flow of posts instead of being pinned at the top.
Arguments:
top_comment -- new top comment, must belong to this thread
"""
if top_comment not in self.comments:
raise Exception("Cannot set foreign comment as top thread comment")
self.top_comment = top_comment
@property
def owner_post(self):
if self.owner_topic != []:
return self.owner_topic[0]
if self.owner_program != []:
return self.owner_program[0]
return None
def delete(self):
"""Recursively delete thread and all associated contents."""
# Remove reference to top comment
self.top_comment = None
db.session.add(self)
db.session.commit()
# Remove comments
for c in self.comments:
c.delete()
# Remove thread
db.session.commit()
db.session.delete(self)
def __repr__(self):
return f'<Thread: #{self.id}>'