models.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # **************************************************************************
  4. # Copyright © 2016 jianglin
  5. # File Name: models.py
  6. # Author: jianglin
  7. # Email: xiyang0807@gmail.com
  8. # Created: 2016-12-15 20:52:07 (CST)
  9. # Last Update:星期四 2017-3-30 15:5:44 (CST)
  10. # By:
  11. # Description:
  12. # **************************************************************************
  13. from datetime import datetime
  14. from flask import current_app
  15. from flask_login import current_user
  16. from flask_maple.models import ModelMixin, ModelTimeMixin, ModelUserMixin
  17. from forums.api.forums.models import Board
  18. from forums.api.user.models import User
  19. from forums.common.models import CommonUserMixin
  20. from forums.extension import db
  21. from forums.count import Count
  22. from forums.filters import safe_markdown, safe_clean, markdown
  23. topic_follower = db.Table(
  24. 'topic_follower',
  25. db.Column('topic_id', db.Integer, db.ForeignKey('topics.id')),
  26. db.Column('follower_id', db.Integer, db.ForeignKey('users.id')))
  27. class Topic(db.Model, ModelMixin):
  28. __tablename__ = 'topics'
  29. CONTENT_TYPE_TEXT = '0'
  30. CONTENT_TYPE_MARKDOWN = '1'
  31. CONTENT_TYPE_ORGMODE = '2'
  32. CONTENT_TYPE = (('0', 'text'), ('1', 'markdown'), ('2', 'org-mode'))
  33. id = db.Column(db.Integer, primary_key=True)
  34. title = db.Column(db.String(81), nullable=False)
  35. content = db.Column(db.Text, nullable=False)
  36. content_type = db.Column(
  37. db.String(10), nullable=False, default=CONTENT_TYPE_MARKDOWN)
  38. created_at = db.Column(
  39. db.DateTime, default=datetime.utcnow(), nullable=False)
  40. updated_at = db.Column(
  41. db.DateTime, default=datetime.utcnow(), onupdate=datetime.utcnow())
  42. is_good = db.Column(db.Boolean, default=False)
  43. is_top = db.Column(db.Boolean, default=False)
  44. author_id = db.Column(
  45. db.Integer, db.ForeignKey(
  46. 'users.id', ondelete="CASCADE"))
  47. author = db.relationship(
  48. User,
  49. backref=db.backref(
  50. 'topics', cascade='all,delete-orphan', lazy='dynamic'),
  51. lazy='joined')
  52. board_id = db.Column(
  53. db.Integer, db.ForeignKey(
  54. 'boards.id', ondelete="CASCADE"))
  55. board = db.relationship(
  56. Board,
  57. backref=db.backref(
  58. 'topics', cascade='all,delete-orphan', lazy='dynamic'),
  59. lazy='joined')
  60. followers = db.relationship(
  61. User,
  62. secondary=topic_follower,
  63. backref=db.backref(
  64. 'following_topics', lazy='dynamic'),
  65. lazy='dynamic')
  66. def is_followed(self, user=None):
  67. if user is None:
  68. user = current_user
  69. return db.session.query(topic_follower).filter(
  70. topic_follower.c.topic_id == self.id,
  71. topic_follower.c.follower_id == user.id).exists()
  72. def is_collected(self, user=None):
  73. if user is None:
  74. user = current_user
  75. return self.collects.filter_by(author_id=user.id).exists()
  76. @property
  77. def text(self):
  78. if self.content_type == Topic.CONTENT_TYPE_TEXT:
  79. return safe_clean(self.content)
  80. elif self.content_type == Topic.CONTENT_TYPE_MARKDOWN:
  81. return markdown(self.content)
  82. return self.content
  83. @property
  84. def newest_reply(self):
  85. return self.replies.order_by('-id').first()
  86. @property
  87. def reply_count(self):
  88. return Count.topic_reply_count(self.id)
  89. @reply_count.setter
  90. def reply_count(self, value):
  91. return Count.topic_reply_count(self.id, value)
  92. @property
  93. def read_count(self):
  94. return Count.topic_read_count(self.id)
  95. @read_count.setter
  96. def read_count(self, value):
  97. return Count.topic_read_count(self.id, value)
  98. def __str__(self):
  99. return self.title
  100. def __repr__(self):
  101. return "<Topic %r>" % self.title
  102. reply_liker = db.Table(
  103. 'reply_liker',
  104. db.Column('reply_id', db.Integer, db.ForeignKey('replies.id')),
  105. db.Column('liker_id', db.Integer, db.ForeignKey('users.id')))
  106. class Reply(db.Model, ModelMixin):
  107. __tablename__ = 'replies'
  108. id = db.Column(db.Integer, primary_key=True)
  109. content = db.Column(db.Text, nullable=False)
  110. created_at = db.Column(
  111. db.DateTime, default=datetime.utcnow(), nullable=False)
  112. updated_at = db.Column(
  113. db.DateTime, default=datetime.utcnow(), onupdate=datetime.utcnow())
  114. topic_id = db.Column(
  115. db.Integer, db.ForeignKey(
  116. 'topics.id', ondelete="CASCADE"))
  117. topic = db.relationship(
  118. Topic,
  119. backref=db.backref(
  120. 'replies', cascade='all,delete-orphan', lazy='dynamic'),
  121. lazy='joined')
  122. author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
  123. author = db.relationship(
  124. User, backref=db.backref(
  125. 'replies', lazy='dynamic'), lazy='joined')
  126. likers = db.relationship(
  127. User,
  128. secondary=reply_liker,
  129. backref=db.backref(
  130. 'like_replies', lazy='dynamic'),
  131. lazy='dynamic')
  132. def is_liked(self, user=None):
  133. if user is None:
  134. user = current_user
  135. if not user.is_authenticated:
  136. return False
  137. return self.likers.filter_by(id=user.id).exists()
  138. @property
  139. def liker_count(self):
  140. return Count.reply_liker_count(self.id)
  141. @liker_count.setter
  142. def liker_count(self, value):
  143. return Count.reply_liker_count(self.id, value)
  144. def __str__(self):
  145. return self.content[:10]
  146. def __repr__(self):
  147. return "<Topic %r>" % self.content[:10]