class Reply(db.Model, ModelMixin): __tablename__ = 'replies' id = db.Column(db.Integer, primary_key=True) content = db.Column(db.Text, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow(), nullable=False) updated_at = db.Column(db.DateTime, default=datetime.utcnow(), onupdate=datetime.utcnow()) is_good = db.Column(db.Integer, default=0, nullable=False) is_bad = db.Column(db.Integer, default=0, nullable=False) is_reply = db.Column(db.SmallInteger, default=0, nullable=False) topic_id = db.Column(db.Integer, db.ForeignKey('topics.id', ondelete="CASCADE")) topic = db.relationship(Topic, backref=db.backref('replies', cascade='all,delete-orphan', lazy='dynamic'), lazy='joined') author_id = db.Column(db.Integer, db.ForeignKey('user.id')) author = db.relationship(User, backref=db.backref('replies', lazy='dynamic'), lazy='joined') likers = db.relationship(User, secondary=reply_liker, backref=db.backref('like_replies', lazy='dynamic'), lazy='dynamic') def is_liked(self, user=None): if user is None: user = current_user if not user.is_authenticated: return False return self.likers.filter_by(id=user.id).exists() @property def liker_count(self): return Count.reply_liker_count(self.id) @liker_count.setter def liker_count(self, value): return Count.reply_liker_count(self.id, value) def __str__(self): return self.content[:10] def __repr__(self): return "<Topic %r>" % self.content[:10]
class Tags(db.Model, ModelMixin): __tablename__ = 'tags' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), nullable=False) description = db.Column(db.String(128), nullable=False) parent_id = db.Column( db.Integer, db.ForeignKey( 'tags.id', ondelete="CASCADE")) parent = db.relationship( 'Tags', remote_side=[id], backref=db.backref( 'children', remote_side=[parent_id], cascade='all,delete-orphan', lazy='dynamic'), lazy='joined', uselist=False) topics = db.relationship( 'Topic', secondary=tag_topic, backref=db.backref( 'tags', lazy='dynamic'), lazy='dynamic') followers = db.relationship( 'User', secondary=tag_follower, backref=db.backref( 'following_tags', lazy='dynamic'), lazy='dynamic') def is_followed(self, user=None): if user is None: user = current_user return db.session.query(tag_follower).filter( tag_follower.c.tag_id == self.id, tag_follower.c.follower_id == user.id).exists() @property def related_tags(self): parent = self.parent if not parent: return [] relateds = parent.children.exclude_by(id=self.id).all() return relateds def __str__(self): return self.name def __repr__(self): return '<Tags %r>' % self.name
class Questions(db.Model, ModelMixin): __tablename__ = 'questions' CONTENT_TYPE_TEXT = '0' CONTENT_TYPE_MARKDOWN = '1' CONTENT_TYPE_ORGMODE = '2' CONTENT_TYPE = (('0', 'text'), ('1', 'markdown'), ('2', 'org-mode')) id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(81), nullable=False) content = db.Column(db.Text, nullable=False) content_type = db.Column(db.String(10), nullable=False, default=CONTENT_TYPE_MARKDOWN) created_at = db.Column(db.DateTime, default=datetime.utcnow(), nullable=False) updated_at = db.Column(db.DateTime, default=datetime.utcnow(), onupdate=datetime.utcnow()) is_good = db.Column(db.Integer, default=0, nullable=False) is_bad = db.Column(db.Integer, default=0, nullable=False) bar_id = db.Column(db.Integer, nullable=False, default=0) is_bar = db.Column(db.SmallInteger, default=0) author_id = db.Column(db.Integer, db.ForeignKey('user.id')) author = db.relationship(User, backref=db.backref('user', lazy='dynamic'), lazy='joined')
class MessageText(CommonTimeMixin, db.Model): __tablename__ = 'message_text' MESSAGE_TYPE_PUBLIC = '0' MESSAGE_TYPE_TOPIC = '1' MESSAGE_TYPE_REPLY = '2' MESSAGE_TYPE_PRIVATE = '3' MESSAGE_TYPE = (('0', '系统消息'), ('1', '主题相关'), ('2', '回复相关'), ('3', '私信')) STATUS_SUBMIT = '0' STATUS_PUBLISH = '1' STATUS_UNDO = '2' STATUS = (('0', '未发布'), ('1', '已发布'), ('2', '撤销发布')) READ_STATUS_UNREAD = '0' READ_STATUS_READ = '1' READ_STATUS = (('0', '未读'), ('1', '已读')) title = db.Column(db.String(128), nullable=False, doc='站内信标题') content = db.Column(db.String(1024), nullable=False, doc='站内信内容') status = db.Column(db.String(128), nullable=False, default=STATUS_SUBMIT, doc='站内信状态') message_type = db.Column(db.String(128), nullable=False, default=MESSAGE_TYPE_PUBLIC, doc='站内信类型') sender_id = db.Column(db.Integer, db.ForeignKey('user.id')) sender = db.relationship('User', backref=db.backref('send_messages', lazy='dynamic'), lazy='joined', uselist=False) @classmethod def get_choice_dict(cls): return dict(messagetext=dict(status=dict(cls.STATUS), message_type=dict(cls.MESSAGE_TYPE), read_status=dict(cls.READ_STATUS))) def __str__(self): return self.title def __repr__(self): return "<MessageText %r>" % self.title @property def read_status(self): ''' 判断站内信是否已读 ''' message = Message.query.filter_by(message_text_id=self.id).first() if message: return '已读' if message.status == Message.STATUS_READ else '已删除' return '未读'
class Message(CommonTimeMixin, db.Model): __tablename__ = 'message' STATUS_UNREAD = '0' STATUS_READ = '1' STATUS_DELETE = '2' STATUS = (('0', '未读'), ('1', '已读'), ('2', '删除')) status = db.Column(db.String(128), nullable=False, default=STATUS_UNREAD, doc='站内信状态') message_text_id = db.Column(db.Integer, db.ForeignKey('message_text.id')) message_text = db.relationship(MessageText, backref=db.backref("messages", cascade='all,delete', lazy='dynamic'), uselist=False, lazy='joined') receiver_id = db.Column(db.Integer, db.ForeignKey('user.id')) receiver = db.relationship('User', backref=db.backref('receive_messages', lazy='dynamic'), lazy='joined', uselist=False) def __str__(self): return self.status def __repr__(self): return "<Message %r>" % self.status @property def title(self): return safe_markdown(self.message_text.title) # return self.message_text.title @property def content(self): return self.message_text.content @classmethod def get_choice_dict(cls): return dict(message=dict(status=dict(cls.STATUS)))
class Collect(db.Model, ModelMixin): __tablename__ = 'collects' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(32), nullable=False) description = db.Column(db.String(256), nullable=True) is_hidden = db.Column(db.Boolean, default=False) created_at = db.Column( db.DateTime, default=datetime.utcnow(), nullable=False) updated_at = db.Column( db.DateTime, default=datetime.utcnow(), onupdate=datetime.utcnow()) author_id = db.Column( db.Integer, db.ForeignKey( 'user.id', ondelete="CASCADE")) author = db.relationship( User, backref=db.backref( 'collects', cascade='all,delete-orphan', lazy='dynamic'), lazy='joined') topics = db.relationship( 'Topic', secondary=topic_collect, backref=db.backref( 'collects', lazy='dynamic'), lazy='dynamic') followers = db.relationship( 'User', secondary=collect_follower, backref=db.backref( 'following_collects', lazy='dynamic'), lazy='dynamic') def is_followed(self, user=None): if user is None: user = current_user return db.session.query(collect_follower).filter( collect_follower.c.collect_id == self.id, collect_follower.c.follower_id == user.id).exists() def __str__(self): return self.name def __repr__(self): return "<Collect %r>" % self.name
def user(cls): name = cls.__name__.lower() if not name.endswith('s'): name = name + 's' if hasattr(cls, 'user_related_name'): name = cls.user_related_name return db.relationship('User', backref=db.backref(name, cascade='all,delete', lazy='dynamic'), uselist=False, lazy='joined')
def user(cls): name = cls.__name__.lower() if not name.endswith('s'): name = name + 's' if hasattr(cls, 'user_related_name'): name = cls.user_related_name return db.relationship( 'User', backref=db.backref( name, cascade='all,delete', lazy='dynamic'), uselist=False, lazy='joined')
class UserSetting(db.Model, ModelMixin): STATUS_ALLOW_ALL = '0' STATUS_ALLOW_AUTHENTICATED = '1' STATUS_ALLOW_OWN = '2' STATUS = (('0', _('ALLOW ALL USER')), ('1', _('ALLOW AUTHENTICATED USER')), ('2', _('ALLOW OWN'))) LOCALE_CHINESE = 'zh' LOCALE_ENGLISH = 'en' LOCALE = (('zh', _('Chinese')), ('en', _('English'))) TIMEZONE_UTC = 'UTC' TIMEZONE = [(i, i) for i in all_timezones] __tablename__ = 'usersetting' id = db.Column(db.Integer, primary_key=True) online_status = db.Column(db.String(10), nullable=False, default=STATUS_ALLOW_ALL) topic_list = db.Column(db.String(10), nullable=False, default=STATUS_ALLOW_ALL) rep_list = db.Column(db.String(10), nullable=False, default=STATUS_ALLOW_ALL) ntb_list = db.Column(db.String(10), nullable=False, default=STATUS_ALLOW_OWN) collect_list = db.Column(db.String(10), nullable=False, default=STATUS_ALLOW_AUTHENTICATED) locale = db.Column(db.String(32), nullable=False, default=LOCALE_CHINESE) timezone = db.Column(db.String(32), nullable=False, default=TIMEZONE_UTC) user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE")) user = db.relationship(User, backref=db.backref("setting", uselist=False, cascade='all,delete', lazy='joined'), uselist=False, lazy='joined') def __repr__(self): return "<UserSetting %r>" % str(self.id) def __str__(self): return "%s's setting" % self.user_id
class Answers(db.Model, ModelMixin): __tablename__ = 'answers' id = db.Column(db.Integer, primary_key=True) content = db.Column(db.Text, nullable=False) is_good = db.Column(db.Integer, default=0, nullable=False) is_bad = db.Column(db.Integer, default=0, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow(), nullable=False) updated_at = db.Column(db.DateTime, default=datetime.utcnow(), onupdate=datetime.utcnow()) questions_id = db.Column(db.Integer) is_reply = db.Column(db.SmallInteger, default=0) author_id = db.Column(db.Integer, db.ForeignKey('user.id')) author = db.relationship(User, backref=db.backref('bar_replies', lazy='dynamic'), lazy='joined')
class Board(db.Model, ModelMixin): __tablename__ = 'boards' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(81), nullable=False) description = db.Column(db.String(128), nullable=False) parent_id = db.Column(db.Integer, db.ForeignKey('boards.id', ondelete="CASCADE")) parent = db.relationship('Board', remote_side=[id], backref=db.backref('children', remote_side=[parent_id], cascade='all,delete-orphan', lazy='dynamic'), lazy='joined', uselist=False) @property def newest_topic(self): return self.topics.order_by('-id').first() @property def topic_count(self): # return self.topics.count() return Count.board_topic_count(self.id) @topic_count.setter def topic_count(self, value): return Count.board_topic_count(self.id, value) @property def post_count(self): return Count.board_post_count(self.id) @post_count.setter def post_count(self, value): return Count.board_post_count(self.id, value) def __str__(self): return self.name def __repr__(self): return '<Board %r>' % self.name
class UserInfo(db.Model, ModelMixin): __tablename__ = 'userinfo' id = db.Column(db.Integer, primary_key=True) avatar = db.Column(db.String(128)) school = db.Column(db.String(128), nullable=True) word = db.Column(db.Text, nullable=True) introduce = db.Column(db.Text, nullable=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE")) user = db.relationship(User, backref=db.backref("info", uselist=False, cascade='all,delete', lazy='joined'), uselist=False, lazy='joined') def __repr__(self): return "<UserInfo %r>" % str(self.id) def __str__(self): return "%s's info" % self.user_id
class User(db.Model, UserMixin, ModelMixin, MailMixin): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(81), unique=True, nullable=False) email = db.Column(db.String(81), unique=True, nullable=False) password = db.Column(db.String(256), nullable=False) is_superuser = db.Column(db.Boolean, default=False) is_confirmed = db.Column(db.Boolean, default=False) register_time = db.Column(db.DateTime, default=datetime.now()) last_login = db.Column(db.DateTime, default=datetime.now()) followers = db.relationship( 'User', secondary=user_follower, primaryjoin=(id == user_follower.c.user_id), secondaryjoin=(id == user_follower.c.follower_id), backref=db.backref('following_users', lazy='dynamic'), lazy='dynamic') def is_followed(self, user=None): if user is None: user = current_user return db.session.query(user_follower).filter( user_follower.c.user_id == self.id, user_follower.c.follower_id == user.id).exists() @property def is_not_confirmed(self): return (not self.is_confirmed and self.id == current_user.id) @property def is_online(self): setting = self.setting if setting.online_status == UserSetting.STATUS_ALLOW_ALL: return self.username in load_online_sign_users() elif setting.online_status == UserSetting.STATUS_ALLOW_AUTHENTICATED: return self.username in load_online_sign_users( ) and current_user.is_authenticated elif setting.online_status == UserSetting.STATUS_ALLOW_OWN: return current_user.id == self.id return False @property def topic_count(self): return self.topics.count() @topic_count.setter def topic_count(self, value): return Count.user_topic_count(self.id, value) @property def reply_count(self): return self.replies.count() @reply_count.setter def reply_count(self, value): return Count.user_reply_count(self.id, value) @property def message_count(self): # return self.receive_messages.filter_by(status='0').count() return Count.user_message_count(self.id) @message_count.setter def message_count(self, value): return Count.user_message_count(self.id, value) @property def send_email_time(self): # return self.receive_messages.filter_by(status='0').count() return Count.user_email_time(self.id) @send_email_time.setter def send_email_time(self, value): return Count.user_email_time(self.id, value) @property def email_is_allowed(self): t = self.send_email_time t = datetime.strptime(t, '%Y-%m-%d %H:%M:%S') now = datetime.now() if t + timedelta(hours=3) < now: self.send_email_time = now.strftime('%Y-%m-%d %H:%M:%S') return True return False def __str__(self): return self.username def __repr__(self): return '<User %r>' % self.username def set_password(self, raw_password): self.password = generate_password_hash(raw_password) def check_password(self, raw_password): return check_password_hash(self.password, raw_password) @property def token(self): config = current_app.config secret_key = config.setdefault('SECRET_KEY') salt = config.setdefault('SECURITY_PASSWORD_SALT') serializer = URLSafeTimedSerializer(secret_key) token = serializer.dumps(self.username, salt=salt) return token @staticmethod def check_token(token, max_age=86400): config = current_app.config secret_key = config.setdefault('SECRET_KEY') salt = config.setdefault('SECURITY_PASSWORD_SALT') serializer = URLSafeTimedSerializer(secret_key) try: username = serializer.loads(token, salt=salt, max_age=max_age) except BadSignature: return False except SignatureExpired: return False user = User.query.filter_by(username=username).first() if user is None: return False return user def send_email(self, *args, **kwargs): kwargs.update(recipients=[self.email]) mail.send_email(*args, **kwargs) def send_email_to_admin(self): '''' When someone registered an account,send email to admin. ''' recipients = current_app.config['RECEIVER'] subject = '{} has registered an account.'.format(self.username) html = '<p>username: {}</p><p>email: {}</p>'.format( self.username, self.email) mail.send_email(subject=subject, html=html, recipients=recipients)
class Topic(db.Model, ModelMixin): __tablename__ = 'topics' __searchable__ = ['title', 'content'] CONTENT_TYPE_TEXT = '0' CONTENT_TYPE_MARKDOWN = '1' CONTENT_TYPE_ORGMODE = '2' CONTENT_TYPE = (('0', 'text'), ('1', 'markdown'), ('2', 'org-mode')) id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(81), nullable=False) content = db.Column(db.Text, nullable=False) content_type = db.Column(db.String(10), nullable=False, default=CONTENT_TYPE_MARKDOWN) created_at = db.Column(db.DateTime, default=datetime.utcnow(), nullable=False) updated_at = db.Column(db.DateTime, default=datetime.utcnow(), onupdate=datetime.utcnow()) is_good = db.Column(db.Boolean, default=False) is_top = db.Column(db.Boolean, default=False) author_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE")) author = db.relationship(User, backref=db.backref('topics', cascade='all,delete-orphan', lazy='dynamic'), lazy='joined') board_id = db.Column(db.Integer, db.ForeignKey('boards.id', ondelete="CASCADE")) board = db.relationship(Board, backref=db.backref('topics', cascade='all,delete-orphan', lazy='dynamic'), lazy='joined') followers = db.relationship(User, secondary=topic_follower, backref=db.backref('following_topics', lazy='dynamic'), lazy='dynamic') __mapper_args__ = {"order_by": created_at.desc()} def is_followed(self, user=None): if user is None: user = current_user return db.session.query(topic_follower).filter( topic_follower.c.topic_id == self.id, topic_follower.c.follower_id == user.id).exists() def is_collected(self, user=None): if user is None: user = current_user return self.collects.filter_by(author_id=user.id).exists() @property def text(self): if self.content_type == Topic.CONTENT_TYPE_TEXT: return safe_clean(self.content) elif self.content_type == Topic.CONTENT_TYPE_MARKDOWN: return markdown(self.content) return self.content @property def newest_reply(self): return self.replies.order_by('-id').first() @property def reply_count(self): return Count.topic_reply_count(self.id) @reply_count.setter def reply_count(self, value): return Count.topic_reply_count(self.id, value) @property def read_count(self): return Count.topic_read_count(self.id) @read_count.setter def read_count(self, value): return Count.topic_read_count(self.id, value) def __str__(self): return self.title def __repr__(self): return "<Topic %r>" % self.title
class User(db.Model, UserMixin): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) followers = db.relationship( 'User', secondary=user_follower, primaryjoin=(id == user_follower.c.user_id), secondaryjoin=(id == user_follower.c.follower_id), backref=db.backref( 'following_users', lazy='dynamic'), lazy='dynamic') def is_followed(self, user=None): if user is None: user = current_user return db.session.query(user_follower).filter( user_follower.c.user_id == self.id, user_follower.c.follower_id == user.id).exists() def login(self, remember=True): login_user(self, remember) identity_changed.send( current_app._get_current_object(), identity=Identity(self.id)) def logout(self): logout_user() identity_changed.send( current_app._get_current_object(), identity=AnonymousIdentity()) @property def is_not_confirmed(self): return (not self.is_confirmed and self.id == current_user.id) @property def is_online(self): setting = self.setting if setting.online_status == UserSetting.STATUS_ALLOW_ALL: return self.username in load_online_sign_users() elif setting.online_status == UserSetting.STATUS_ALLOW_AUTHENTICATED: return self.username in load_online_sign_users( ) and current_user.is_authenticated elif setting.online_status == UserSetting.STATUS_ALLOW_OWN: return current_user.id == self.id return False @property def topic_count(self): return self.topics.count() @topic_count.setter def topic_count(self, value): return Count.user_topic_count(self.id, value) @property def reply_count(self): return self.replies.count() @reply_count.setter def reply_count(self, value): return Count.user_reply_count(self.id, value) @property def message_count(self): # return self.receive_messages.filter_by(status='0').count() return Count.user_message_count(self.id) @message_count.setter def message_count(self, value): return Count.user_message_count(self.id, value) @property def send_email_time(self): # return self.receive_messages.filter_by(status='0').count() return Count.user_email_time(self.id) @send_email_time.setter def send_email_time(self, value): return Count.user_email_time(self.id, value) @property def email_is_allowed(self): t = self.send_email_time t = datetime.strptime(t, '%Y-%m-%d %H:%M:%S') now = datetime.now() if t + timedelta(hours=3) < now: self.send_email_time = now.strftime('%Y-%m-%d %H:%M:%S') return True return False def send_email(self, *args, **kwargs): kwargs.update(recipients=[self.email]) mail.send_email(*args, **kwargs) def send_email_to_admin(self): '''' When someone registered an account,send email to admin. ''' recipients = current_app.config['RECEIVER'] subject = '{} has registered an account.'.format(self.username) html = '<p>username: {}</p><p>email: {}</p>'.format(self.username, self.email) mail.send_email(subject=subject, html=html, recipients=recipients)