Coverage for src/couchers/models/discussions.py: 100%
58 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-08 00:20 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-08 00:20 +0000
1from sqlalchemy import BigInteger, Column, DateTime, ForeignKey, String, UniqueConstraint, func
2from sqlalchemy.orm import backref, column_property, relationship
4from couchers.models.base import Base, communities_seq
7class Discussion(Base):
8 """
9 forum board
10 """
12 __tablename__ = "discussions"
14 id = Column(BigInteger, communities_seq, primary_key=True, server_default=communities_seq.next_value())
16 title = Column(String, nullable=False)
17 content = Column(String, nullable=False)
18 thread_id = Column(ForeignKey("threads.id"), nullable=False, unique=True)
19 created = Column(DateTime(timezone=True), nullable=False, server_default=func.now())
21 creator_user_id = Column(ForeignKey("users.id"), nullable=False, index=True)
22 owner_cluster_id = Column(ForeignKey("clusters.id"), nullable=False, index=True)
24 slug = column_property(func.slugify(title))
26 thread = relationship("Thread", backref="discussion", uselist=False)
28 subscribers = relationship("User", backref="discussions", secondary="discussion_subscriptions", viewonly=True)
30 creator_user = relationship("User", backref="created_discussions", foreign_keys="Discussion.creator_user_id")
31 owner_cluster = relationship("Cluster", backref=backref("owned_discussions", lazy="dynamic"), uselist=False)
34class DiscussionSubscription(Base):
35 """
36 users subscriptions to discussions
37 """
39 __tablename__ = "discussion_subscriptions"
40 __table_args__ = (UniqueConstraint("discussion_id", "user_id"),)
42 id = Column(BigInteger, primary_key=True)
44 user_id = Column(ForeignKey("users.id"), nullable=False, index=True)
45 discussion_id = Column(ForeignKey("discussions.id"), nullable=False, index=True)
46 joined = Column(DateTime(timezone=True), nullable=False, server_default=func.now())
47 left = Column(DateTime(timezone=True), nullable=True)
49 user = relationship("User", backref="discussion_subscriptions")
50 discussion = relationship("Discussion", backref="discussion_subscriptions")
53class Thread(Base):
54 """
55 Thread
56 """
58 __tablename__ = "threads"
60 id = Column(BigInteger, primary_key=True)
62 created = Column(DateTime(timezone=True), nullable=False, server_default=func.now())
63 deleted = Column(DateTime(timezone=True), nullable=True)
66class Comment(Base):
67 """
68 Comment
69 """
71 __tablename__ = "comments"
73 id = Column(BigInteger, primary_key=True)
75 thread_id = Column(ForeignKey("threads.id"), nullable=False, index=True)
76 author_user_id = Column(ForeignKey("users.id"), nullable=False)
77 content = Column(String, nullable=False) # CommonMark without images
78 created = Column(DateTime(timezone=True), nullable=False, server_default=func.now())
79 deleted = Column(DateTime(timezone=True), nullable=True)
81 thread = relationship("Thread", backref="comments")
84class Reply(Base):
85 """
86 Reply
87 """
89 __tablename__ = "replies"
91 id = Column(BigInteger, primary_key=True)
93 comment_id = Column(ForeignKey("comments.id"), nullable=False, index=True)
94 author_user_id = Column(ForeignKey("users.id"), nullable=False)
95 content = Column(String, nullable=False) # CommonMark without images
96 created = Column(DateTime(timezone=True), nullable=False, server_default=func.now())
97 deleted = Column(DateTime(timezone=True), nullable=True)
99 comment = relationship("Comment", backref="replies")
102class ClusterDiscussionAssociation(Base):
103 """
104 discussions related to clusters
105 """
107 __tablename__ = "cluster_discussion_associations"
108 __table_args__ = (UniqueConstraint("discussion_id", "cluster_id"),)
110 id = Column(BigInteger, primary_key=True)
112 discussion_id = Column(ForeignKey("discussions.id"), nullable=False, index=True)
113 cluster_id = Column(ForeignKey("clusters.id"), nullable=False, index=True)
115 discussion = relationship("Discussion", backref="cluster_discussion_associations")
116 cluster = relationship("Cluster", backref="cluster_discussion_associations")