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

1from sqlalchemy import BigInteger, Column, DateTime, ForeignKey, String, UniqueConstraint, func 

2from sqlalchemy.orm import backref, column_property, relationship 

3 

4from couchers.models.base import Base, communities_seq 

5 

6 

7class Discussion(Base): 

8 """ 

9 forum board 

10 """ 

11 

12 __tablename__ = "discussions" 

13 

14 id = Column(BigInteger, communities_seq, primary_key=True, server_default=communities_seq.next_value()) 

15 

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()) 

20 

21 creator_user_id = Column(ForeignKey("users.id"), nullable=False, index=True) 

22 owner_cluster_id = Column(ForeignKey("clusters.id"), nullable=False, index=True) 

23 

24 slug = column_property(func.slugify(title)) 

25 

26 thread = relationship("Thread", backref="discussion", uselist=False) 

27 

28 subscribers = relationship("User", backref="discussions", secondary="discussion_subscriptions", viewonly=True) 

29 

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) 

32 

33 

34class DiscussionSubscription(Base): 

35 """ 

36 users subscriptions to discussions 

37 """ 

38 

39 __tablename__ = "discussion_subscriptions" 

40 __table_args__ = (UniqueConstraint("discussion_id", "user_id"),) 

41 

42 id = Column(BigInteger, primary_key=True) 

43 

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) 

48 

49 user = relationship("User", backref="discussion_subscriptions") 

50 discussion = relationship("Discussion", backref="discussion_subscriptions") 

51 

52 

53class Thread(Base): 

54 """ 

55 Thread 

56 """ 

57 

58 __tablename__ = "threads" 

59 

60 id = Column(BigInteger, primary_key=True) 

61 

62 created = Column(DateTime(timezone=True), nullable=False, server_default=func.now()) 

63 deleted = Column(DateTime(timezone=True), nullable=True) 

64 

65 

66class Comment(Base): 

67 """ 

68 Comment 

69 """ 

70 

71 __tablename__ = "comments" 

72 

73 id = Column(BigInteger, primary_key=True) 

74 

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) 

80 

81 thread = relationship("Thread", backref="comments") 

82 

83 

84class Reply(Base): 

85 """ 

86 Reply 

87 """ 

88 

89 __tablename__ = "replies" 

90 

91 id = Column(BigInteger, primary_key=True) 

92 

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) 

98 

99 comment = relationship("Comment", backref="replies") 

100 

101 

102class ClusterDiscussionAssociation(Base): 

103 """ 

104 discussions related to clusters 

105 """ 

106 

107 __tablename__ = "cluster_discussion_associations" 

108 __table_args__ = (UniqueConstraint("discussion_id", "cluster_id"),) 

109 

110 id = Column(BigInteger, primary_key=True) 

111 

112 discussion_id = Column(ForeignKey("discussions.id"), nullable=False, index=True) 

113 cluster_id = Column(ForeignKey("clusters.id"), nullable=False, index=True) 

114 

115 discussion = relationship("Discussion", backref="cluster_discussion_associations") 

116 cluster = relationship("Cluster", backref="cluster_discussion_associations")