class Article(db.Model): __tablename__ = 'articles' __searchable__ = ['title', 'body'] __analyzer__ = ChineseAnalyzer() id = db.Column(db.Integer, primary_key=True) number = db.Column(db.Integer, default=random_number, unique=True) title = db.Column(db.String(200), default='') body = db.Column(LONGTEXT, default='') body_html = db.Column(LONGTEXT) body_abstract = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) author_id = db.Column(db.Integer, db.ForeignKey('users.id')) author = db.relationship('User', backref='articles') repository_id = db.Column(db.String(36)) status = db.Column(db.String(200), default='') version_remark = db.Column(db.TEXT, default='') version_timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) @staticmethod def query_published(): return Article.query.filter_by(status='published') def to_json(self, level='brief'): json = { 'id': self.id, 'number': self.number, 'title': self.title, 'timestamp': self.timestamp.replace(tzinfo=timezone.utc).isoformat(), 'author': self.author.to_json(level) } json['plugin'] = Signal.send('to_json', article=self, level=level) if level.startswith('admin_'): json['repositoryId'] = self.repository_id json['status'] = self.status json['versionTimestamp'] = self.version_timestamp if level == 'admin_brief': return json json['bodyAbstract'] = self.body_abstract if level == 'admin_basic': return json json['body'] = self.body if level == 'admin_full': return json else: if level == 'brief': return json json['bodyAbstract'] = self.body_abstract if level == 'basic': return json json['body'] = self.body json['bodyHtml'] = self.body_html if level == 'full': return json
class Tag(db.Model): __tablename__ = 'tags' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(200)) slug = db.Column(db.String(200)) description = db.Column(db.Text) articles = db.relationship('Article', secondary=association_table, backref='tags') @staticmethod def create(id=None, name=None, slug=None, description=None): filter_kwargs = {} for param in ['id', 'name', 'slug', 'description']: if eval(param) is not None: filter_kwargs[param] = eval(param) return Tag(**filter_kwargs) def get_info(self): return { 'name': self.name, 'url': url_for('.index', tag=self.slug), 'url_params': { 'tag': self.slug } } def to_json(self, level='brief'): json = {'name': self.name, 'slug': self.slug} if level.startswith('admin_'): json['id'] = self.id json['countArticle'] = len(self.articles) if level == 'admin_brief': return json json['description'] = self.description if level == 'admin_full': return json else: if level == 'brief': return json return json
class Message(db.Model): __tablename__ = 'comment_to_mail_messages' id = db.Column(db.Integer, primary_key=True) comment_id = db.Column(db.Integer, db.ForeignKey('comments.id')) status = db.Column(db.Text) job_id = db.Column(db.String(255)) message_id = db.Column(db.Text) sent_date_time = db.Column(db.DateTime) recipient = db.Column(db.Text) web_link = db.Column(db.Text) comment = db.relationship('Comment', backref='message')
class Template(db.Model): __tablename__ = 'templates' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(200)) slug = db.Column(db.String(200)) description = db.Column(db.Text) body = db.Column(db.Text) articles = db.relationship('Article', secondary=template_article_association_table, backref=backref('template', uselist=False)) pages = db.relationship('Page', secondary=template_page_association_table, backref=backref('template', uselist=False)) def get_info(self): return { 'name': self.name, 'url': url_for('.index', template=self.slug), 'url_params': { 'template': self.slug } }
class Attachment(db.Model): __tablename__ = 'attachments' id = db.Column(db.Integer, primary_key=True) original_filename = db.Column(db.String(200)) filename = db.Column(db.String(200), unique=True) file_path = db.Column(db.String(200)) file_extension = db.Column(db.String(32)) file_size = db.Column(db.Integer) mime = db.Column(db.String(64)) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) md5 = db.Column(db.String(32)) articles = db.relationship('Article', secondary=attachment_article_association_table, backref='attachments') pages = db.relationship('Page', secondary=attachment_page_association_table, backref='attachments') @staticmethod def create(file_path, original_filename, file_extension, id=None, mime=None, timestamp=None): random_filename = uuid.uuid4().hex + '.' + file_extension if timestamp is not None: dt = timestamp else: dt = datetime.today() relative_file_path = os.path.join(str(dt.year), '%02d' % dt.month, random_filename) abs_file_path = os.path.join(current_app.config['UPLOAD_FOLDER'], relative_file_path) os.makedirs(os.path.dirname(abs_file_path), exist_ok=True) shutil.copy(file_path, abs_file_path) filter_kwargs = {} for param in ['id', 'mime', 'timestamp']: if eval(param) is not None: filter_kwargs[param] = eval(param) return Attachment(original_filename=original_filename, filename=random_filename, file_path=relative_file_path, file_extension=file_extension, **filter_kwargs) @staticmethod def on_change_file_path(target, value, oldvalue, initiator): abs_file_path = os.path.join(current_app.config['UPLOAD_FOLDER'], value) target.file_size = os.path.getsize(abs_file_path) target.md5 = md5(abs_file_path) @staticmethod def after_delete(mapper, connection, target): abs_file_path = os.path.join(current_app.config['UPLOAD_FOLDER'], target.file_path) os.remove(abs_file_path) def to_json(self, level='basic'): json = { 'id': self.id, 'filename': self.original_filename, 'size': self.file_size } if level == 'basic': return json
class Page(db.Model): __tablename__ = 'pages' id = db.Column(db.Integer, primary_key=True) number = db.Column(db.Integer, default=random_number, unique=True) title = db.Column(db.String(200), default='') _slug = db.Column('slug', db.String(200), default='') body = db.Column(db.Text, default='') body_html = db.Column(db.Text) body_abstract = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) author_id = db.Column(db.Integer, db.ForeignKey('users.id')) author = db.relationship(User, backref='pages') repository_id = db.Column(db.String(36)) status = db.Column(db.String(200), default='') version_remark = db.Column(db.TEXT, default='') version_timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) @hybrid_property def slug(self): return self._slug @slug.setter def slug(self, slug): self._slug = slugify(slug) @staticmethod def query_published(): return Page.query.filter_by(status='published') def to_json(self, level='basic'): json = { 'id': self.id, 'number': self.number, 'title': self.title, 'timestamp': self.timestamp, 'author': self.author.to_json() } json['plugin'] = Signal.send('to_json', page=self, level=level) if level.startswith('admin_'): json['repositoryId'] = self.repository_id json['status'] = self.status json['versionTimestamp'] = self.version_timestamp if level == 'admin_brief': return json json['bodyAbstract'] = self.body_abstract if level == 'admin_basic': return json json['body'] = self.body if level == 'admin_full': return json else: if level == 'brief': return json json['bodyAbstract'] = self.body_abstract if level == 'basic': return json json['body'] = self.body json['bodyHtml'] = self.body_html if level == 'full': return json if level == 'basic': return json json['body'] = self.body json['bodyHtml'] = self.body_html if level == 'full': return json
class ViewCount(db.Model): __tablename__ = 'view_counts' id = db.Column(db.Integer, primary_key=True) repository_id = db.Column(db.String(36), unique=True) count = db.Column(db.Integer, default=0)
class Settings(db.Model): __tablename__ = 'settings' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Text) slug = db.Column(db.String(100)) _value = db.Column('value', db.Text) description = db.Column(db.Text) value_type = db.Column(db.String(40)) category = db.Column(db.String(40)) timestamp = db.Column(db.DateTime, default=datetime.utcnow) visibility = db.Column(db.String(40), default='visible') _default_categories = {} @property def value(self): return self.get_value_self() @value.setter def value(self, value): self._value = value @classmethod def get_setting(cls, slug, category=None): return Settings.query.filter_by(slug=slug).first() @staticmethod def get_value(slug, category='bearblog'): item = Settings.query.filter_by(slug=slug, category=category).first() if item is not None: return item.get_value_self() return None def get_value_self(self): if self.value_type is None: return self._value if self.value_type == 'str_list': return self._value.split() if self.value_type == 'signal': return json.loads(self._value) return eval(self.value_type)(self._value) @staticmethod def get(slug, category='settings'): item = Settings.query.filter_by(slug=slug, category=category).first() if item is None: return None return { 'raw_value': item._value, 'value': Settings.get_value(slug, category), 'description': item.description, 'value_type': item.value_type } @classmethod def set_setting(cls, slug, category=None, **kwargs): if category is None: frame = sys._getframe(1) caller_file = os.path.abspath(frame.f_code.co_filename) matches = [category for category in cls._default_categories if caller_file.startswith(category)] if matches: category = cls._default_categories[max(matches, key=len)] if category is None: category = 'settings' cls.set(slug, category, **kwargs) @staticmethod def set(slug, category='settings', **kwargs): item = Settings.query.filter_by(slug=slug).first() if item is None: item = Settings(slug=slug, category=category) db.session.add(item) db.session.flush() for attr, value in kwargs.items(): if value is not None: setattr(item, attr, value) db.session.commit() @classmethod def add_default_category(cls, path, category): cls._default_categories[path] = category def to_json(self): return { 'id': self.id, 'name': self.name, 'slug': self.slug, 'rawValue': self._value, 'value': self.value, 'description': self.description, 'rawValueType': self.value_type, 'category': self.category, 'timestamp': self.timestamp, 'visibility': self.visibility }
class Comment(db.Model): __tablename__ = 'comments' id = db.Column(db.Integer, primary_key=True) body = db.Column(db.Text) body_html = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) author_id = db.Column(db.Integer, db.ForeignKey('users.id')) ip = db.Column(db.String(64)) agent = db.Column(db.String(200)) parent = db.Column(db.Integer) author = db.relationship('User', backref='comments') article_id = db.Column(db.Integer, db.ForeignKey('articles.id')) page_id = db.Column(db.Integer, db.ForeignKey('pages.id')) article = db.relationship('Article', backref='comments') page = db.relationship('Page', backref='comments') @staticmethod def create(id=None, body=None, body_html=None, timestamp=None, ip=None, agent=None, parent=None, author=None): filter_kwargs = {} for param in ['id', 'body', 'body_html', 'timestamp', 'ip', 'agent', 'parent', 'author']: if eval(param) is not None: filter_kwargs[param] = eval(param) return Comment(**filter_kwargs) @staticmethod def on_changed_body(target, value, oldvalue, initiator): class Renderer(mistune.Renderer): def __init__(self): super().__init__() self.toc_count = 0 def header(self, text, level, raw=None): rv = '<h%d id="toc-%d">%s</h%d>\n' % ( level, self.toc_count, text, level ) self.toc_count += 1 return rv renderer = Renderer() markdown = mistune.Markdown(renderer=renderer) target.body_html = markdown(value) def to_json(self, level='brief'): def get_comment_to(comment): if comment.article is not None: return comment.article.to_json('admin_brief') if comment.page is not None: return comment.page.to_json('admin_brief') json = { 'id': self.id } if level.startswith('admin_'): json['body'] = self.body json['timestamp'] = self.timestamp json['author'] = self.author.to_json('admin_brief') json['ip'] = self.ip json['to'] = get_comment_to(self) if level == 'admin_full': return json else: json['body'] = self.body json['timestamp'] = self.timestamp json['author'] = self.author.to_json('basic') if level == 'basic': return json