models.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. # -*- coding: utf-8 -*-
  2. """
  3. flaskbb.forum.models
  4. ~~~~~~~~~~~~~~~~~~~~
  5. It provides the models for the forum
  6. :copyright: (c) 2013 by the FlaskBB Team.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. from datetime import datetime
  10. from flaskbb.extensions import db
  11. from flaskbb.helpers import DenormalizedText
  12. class Post(db.Model):
  13. __tablename__ = "posts"
  14. id = db.Column(db.Integer, primary_key=True)
  15. topic_id = db.Column(db.Integer, db.ForeignKey("topics.id", use_alter=True,
  16. name="fk_topic_id",
  17. ondelete="CASCADE"))
  18. user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
  19. content = db.Column(db.Text)
  20. date_created = db.Column(db.DateTime, default=datetime.utcnow())
  21. date_modified = db.Column(db.DateTime)
  22. def save(self, user=None, topic=None):
  23. # update/edit the post
  24. if self.id:
  25. db.session.add(self)
  26. db.session.commit()
  27. return self
  28. # Adding a new post
  29. if user and topic:
  30. self.user_id = user.id
  31. self.topic_id = topic.id
  32. self.date_created = datetime.utcnow()
  33. # This needs to be done before I update the last_post_id.
  34. db.session.add(self)
  35. db.session.commit()
  36. # Now lets update the last post id
  37. topic.last_post_id = self.id
  38. topic.forum.last_post_id = self.id
  39. # Update the post counts
  40. user.post_count += 1
  41. topic.post_count += 1
  42. topic.forum.post_count += 1
  43. # And commit it!
  44. db.session.add(topic)
  45. db.session.commit()
  46. return self
  47. def delete(self):
  48. # This will delete the whole topic
  49. if self.topic.first_post_id == self.id:
  50. self.topic.delete()
  51. return self
  52. # Delete the last post
  53. if self.topic.last_post_id == self.id:
  54. # Now the second last post will be the last post
  55. self.topic.last_post_id = self.topic.second_last_post
  56. self.topic.forum.last_post_id = self.topic.second_last_post
  57. db.session.commit()
  58. # Update the post counts
  59. self.user.post_count -= 1
  60. self.topic.post_count -= 1
  61. self.topic.forum.post_count -= 1
  62. # Is there a better way to do this?
  63. db.session.delete(self)
  64. db.session.commit()
  65. return self
  66. class Topic(db.Model):
  67. __tablename__ = "topics"
  68. id = db.Column(db.Integer, primary_key=True)
  69. forum_id = db.Column(db.Integer, db.ForeignKey("forums.id", use_alter=True,
  70. name="fk_forum_id"))
  71. title = db.Column(db.String)
  72. user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
  73. date_created = db.Column(db.DateTime, default=datetime.utcnow())
  74. locked = db.Column(db.Boolean, default=False)
  75. important = db.Column(db.Boolean, default=False)
  76. views = db.Column(db.Integer, default=0)
  77. post_count = db.Column(db.Integer, default=0)
  78. # One-to-one (uselist=False) relationship between first_post and topic
  79. first_post_id = db.Column(db.Integer, db.ForeignKey("posts.id",
  80. ondelete="CASCADE"))
  81. first_post = db.relationship("Post", backref="first_post", uselist=False,
  82. foreign_keys=[first_post_id])
  83. # One-to-one
  84. last_post_id = db.Column(db.Integer, db.ForeignKey("posts.id",
  85. ondelete="CASCADE",
  86. onupdate="CASCADE"))
  87. last_post = db.relationship("Post", backref="last_post", uselist=False,
  88. foreign_keys=[last_post_id])
  89. # One-to-many
  90. posts = db.relationship("Post", backref="topic", lazy="joined",
  91. primaryjoin="Post.topic_id == Topic.id",
  92. cascade="all, delete-orphan", post_update=True)
  93. def __init__(self, title=None):
  94. if title:
  95. self.title = title
  96. @property
  97. def second_last_post(self):
  98. """
  99. Returns the second last post.
  100. """
  101. return self.posts[-2].id
  102. def save(self, user=None, forum=None, post=None):
  103. # Updates the topic - Because the thread title (by intention)
  104. # isn't change able, so we are just going to update the post content
  105. if self.id:
  106. db.session.add(self)
  107. db.session.commit()
  108. return self
  109. # Set the forum and user id
  110. self.forum_id = forum.id
  111. self.user_id = user.id
  112. # Update the topic count
  113. forum.topic_count += 1
  114. # Insert and commit the topic
  115. db.session.add(self)
  116. db.session.commit()
  117. # Create the topic post
  118. post.save(user, self)
  119. # Update the first post id
  120. self.first_post_id = post.id
  121. db.session.commit()
  122. return self
  123. def delete(self, users=None):
  124. topic = Topic.query.filter_by(forum_id=self.forum_id).\
  125. order_by(Topic.last_post_id.desc())
  126. if topic and topic[0].id == self.id:
  127. try:
  128. self.forum.last_post_id = topic[1].last_post_id
  129. # Catch an IndexError when you delete the last topic in the forum
  130. except IndexError:
  131. self.forum.last_post_id = 0
  132. # These things needs to be stored in a variable before they are deleted
  133. forum = self.forum
  134. # Delete the topic
  135. db.session.delete(self)
  136. db.session.commit()
  137. # Update the post counts
  138. if users:
  139. # If someone knows a better method for this,
  140. # feel free to improve it :)
  141. for user in users:
  142. user.post_count = Post.query.filter_by(user_id=user.id).count()
  143. db.session.commit()
  144. forum.topic_count = Topic.query.filter_by(
  145. forum_id=self.forum_id).count()
  146. forum.post_count = Post.query.filter(
  147. Post.topic_id == Topic.id,
  148. Topic.forum_id == self.forum_id).count()
  149. db.session.commit()
  150. return self
  151. class Forum(db.Model):
  152. __tablename__ = "forums"
  153. id = db.Column(db.Integer, primary_key=True)
  154. title = db.Column(db.String)
  155. description = db.Column(db.String)
  156. position = db.Column(db.Integer, default=0)
  157. category_id = db.Column(db.Integer, db.ForeignKey("categories.id",
  158. use_alter=True,
  159. name="fk_category_id"))
  160. post_count = db.Column(db.Integer, default=0)
  161. topic_count = db.Column(db.Integer, default=0)
  162. # One-to-one
  163. last_post_id = db.Column(db.Integer, db.ForeignKey("posts.id"))
  164. last_post = db.relationship("Post", backref="last_post_forum",
  165. uselist=False, foreign_keys=[last_post_id])
  166. # One-to-many
  167. topics = db.relationship("Topic", backref="forum", lazy="joined")
  168. moderators = db.Column(DenormalizedText)
  169. def add_moderator(self, user_id):
  170. self.moderators.add(user_id)
  171. def remove_moderator(self, user_id):
  172. self.moderators.remove(user_id)
  173. def save(self):
  174. db.session.add(self)
  175. db.session.commit()
  176. return self
  177. def delete(self):
  178. db.session.delete(self)
  179. db.session.commit()
  180. return self
  181. class Category(db.Model):
  182. __tablename__ = "categories"
  183. id = db.Column(db.Integer, primary_key=True)
  184. title = db.Column(db.String)
  185. description = db.Column(db.String)
  186. position = db.Column(db.Integer, default=0)
  187. # One-to-many
  188. forums = db.relationship("Forum", backref="category", lazy="joined",
  189. primaryjoin="Forum.category_id == Category.id")
  190. def save(self):
  191. db.session.add(self)
  192. db.session.commit()
  193. return self
  194. def delete(self):
  195. db.session.delete(self)
  196. db.session.commit()
  197. return self