class Comment(BaseMixin, LikeMixin, db.Model): __tablename__ = 'comments' user_id = db.Column(db.Integer) target_id = db.Column(db.Integer) # 评论的目标 target_kind = db.Column(db.Integer) # 评论目标的类型 ref_id = db.Column(db.Integer, default=0) # 引用其他人的评论, 可以不引用 content = PropsItem('content', '') kind = K_COMMENT # 自己是评论类型 __table_args__ = (db.Index('idx_ti_tk_ui', target_id, target_kind, user_id), ) @cached_hybrid_property def html_content(self): return self.content @cached_hybrid_property def user(self): return User.get(self.user_id) @classmethod def __flush_event__(cls, target): """BaseModel里面配置了event, 会在增删改的时候把缓存清空""" for key in (MC_KEY_COMMENT_LIST, MC_KEY_COMMENT_N): rdb.delete(key % (target.id, target.kind))
class Book(PropsMixin): def __init__(self): self.id = id(self) title = PropsItem(name='title') date = DatePropsItem(name='date') def get_uuid(self): return '/bran/{0.__class__.__name__}/{0.id}'.format(self)
class CommentItem(ActionMixin, LikeMixin, db.Model): __tablename__ = "comment_items" user_id = db.Column(db.Integer) target_id = db.Column(db.Integer) target_kind = db.Column(db.Integer) ref_id = db.Column(db.Integer, default=0) content = PropsItem("content", "") kind = K_COMMENT action_type = "comment" __table_args__ = (db.Index("idx_ti_tk_ui", target_id, target_kind, user_id), ) @cached_hybrid_property def user(self): return User.get(self.user_id)
class CommentItem(ActionMixin, LikeMixin, db.Model): __tablename__ = 'comment_items' user_id = db.Column(db.Integer) target_id = db.Column(db.Integer) target_kind = db.Column(db.Integer) ref_id = db.Column(db.Integer, default=0) # 评论分文章评论,还有评论的评论,文章评论设置为0 content = PropsItem() kind = K_COMMENT action_type = 'comment' __table_args__ = (db.Index('idx_ti_tk_ui', target_id, target_kind, user_id), ) @cached_property def html_content(self): return self.content @cached_property def user(self): return User.get(self.user_id)
class CommentItem(ActionMixin, db.Model): __tablename__ = 'comment_items' user_id = db.Column(db.Integer) target_id = db.Column(db.Integer) target_kind = db.Column(db.Integer) ref_id = db.Column( db.Integer, default=0) # ref_id = 0 if comment on Post, else comment on comment. content = PropsItem('content', '') # this field is stored in key-value db kind = K_COMMENT action_type = 'comment' __table_args__ = (db.Index('idx_ti_tk_ui', target_id, target_kind, user_id), ) @cached_hybrid_property def html_content(self): return self.content @cached_hybrid_property def user(self): return User.get(self.user_id)
class Post(BaseMixin, CommentMixin, LikeMixin, CollectMixin, db.Model): __tablename__ = 'posts' author_id = db.Column(db.Integer) title = db.Column(db.String(128), default='') orig_url = db.Column(db.String(255), default='') can_comment = db.Column(db.Boolean, default=True) content = PropsItem( 'content', '' ) # key-value db field, since `content` is only stored, normally not need search/filter/query... kind = K_POST __table_args__ = (db.Index('idx_title', title), db.Index('idx_authorId', author_id)) def url(self): return '/{}/{}/'.format(self.__class__.__name__.lower(), self.id) @classmethod def __flush_event__(cls, target): rdb.delete(MC_KEY_ALL_TAGS) @classmethod def get(cls, identifier): if is_numeric(identifier): return cls.cache.get(identifier) # get post via title return cls.cache.filter(title=identifier).first() @property @cache(MC_KEY_POST_TAGS % ('{self.id}')) def tags(self): at_ids = PostTag.query.with_entities( PostTag.tag_id).filter(PostTag.post_id == self.id).all() tags = Tag.query.filter(Tag.id.in_((id for id, in at_ids))).all() return tags @cached_hybrid_property def abstract_content(self): return trunc_utf8(self.content, 100) @cached_hybrid_property def author(self): return User.get(self.author_id) @classmethod def create_or_update(cls, **kwargs): # not default `create_or_update' in BaseMixin tags = kwargs.pop('tags', []) created, obj = super(Post, cls).create_or_update(**kwargs) if tags: PostTag.update_multi(obj.id, tags, []) if created: from handler.tasks import feed_post, reindex reindex.delay(obj.id, obj.kind, op_type='create') feed_post.delay(obj.id) return created, obj def delete(self): id = self.id super().delete() # defined in BaseMixin for pt in PostTag.query.filter_by(post_id=id): pt.delete() from handler.tasks import remove_post_from_feed remove_post_from_feed.delay(self.id, self.author_id) @cached_hybrid_property def netloc(self): return '{0.scheme}://{0.netloc}'.format(urlparse(self.orig_url)) @staticmethod def _flush_insert_event(mapper, connection, target): target._flush_event(mapper, connection, target) target.__flush_insert_event__(target)
class Post(BaseMixin, CommentMixin, LikeMixin, CollectMixin, db.Model): __tablename__ = "posts" author_id = db.Column(db.Integer) title = db.Column(db.String(128), default="") orig_url = db.Column(db.String(255), default="") can_comment = db.Column(db.Boolean, default=True) content = PropsItem("content", "") kind = K_POST __table_args__ = (db.Index("idx_title", title), db.Index("idx_authorId", author_id)) @cached_hybrid_property def abstract_content(self): return trunc_utf8(self.content, 100) @cached_hybrid_property def author(self): return User.get(self.author_id) @cached_hybrid_property def orig_netloc(self): return urlparse(self.orig_url).netloc @classmethod def get(cls, identifier): if is_numeric(identifier): return cls.cache.get(identifier) return cls.cache.filter(title=identifier).first() @property @cache(MC_KEY_POST_TAGS.format("{self.id}")) def tags(self): at_ids = ( PostTag.query.with_entities(PostTag.tag_id) .filter(PostTag.post_id == self.id) .all() ) tags = Tag.query.filter(Tag.id.in_((id for id, in at_ids))).all() return tags @classmethod def create_or_update(cls, **kwargs): tags = kwargs.pop("tags", []) created, obj = super(Post, cls).create_or_update(**kwargs) if tags: PostTag.update_multi(obj.id, tags) if created: from handler.tasks import feed_post, reindex reindex.delay(obj.id, obj.kind, op_type="create") feed_post.delay(obj.id) return created, obj def delete(self): post_id = self.id author_id = self.author_id super().delete() for pt in PostTag.query.filter_by(post_id=post_id): pt.delete() from handler.tasks import remove_post_from_feed remove_post_from_feed.delay(post_id, author_id) @classmethod def __flush_event__(cls, target): rdb.delete(MC_KEY_ALL_TAGS) @staticmethod def _flush_insert_event(mapper, connection, target): target._flush_event(mapper, connection, target) target.__flush_insert_event__(target)
class Post(BaseMixin, CommentMixin, LikeMixin, CollectMixin, db.Model): __tablename__ = 'posts' author_id = db.Column(db.Integer) title = db.Column(db.String(128), default='') orig_url = db.Column(db.String(255), default='') can_comment = db.Column(db.Boolean, default=True) content = PropsItem('content', '') kind = K_POST __table_args__ = ( db.Index('idx_title', title), ) def url(self): return '/{}/{}/'.format(self.__class__.__name__.lower(), self.id) @classmethod def __flush_event__(cls, target): rdb.delete(MC_KEY_ALL_TAGS) @classmethod def get(cls, identifier): if is_numeric(identifier): return cls.cache.get(identifier) return cls.cache.filter(title=identifier).first() @property def tags(self): at_ids = PostTag.query.with_entities( PostTag.tag_id).filter( PostTag.post_id == self.id ).all() tags = Tag.query.filter(Tag.id.in_(id_ for id_, in at_ids)).all() return tags @cached_hybrid_property def abstract_content(self): return trunc_utf8(self.content, 100) @cached_hybrid_property def author(self): return User.get(self.author_id) @classmethod def create_or_update(cls, **kwargs): tags = kwargs.pop('tags', []) created, obj = super(Post, cls).create_or_update(**kwargs) if tags: PostTag.update_multi(obj.id, tags) return created, obj def delete(self): id = self.id super().delete() for pt in PostTag.query.filter_by(post_id=id): pt.delete() @cached_hybrid_property def netloc(self): return '{0.scheme}://{0.netloc}'.format(urlparse(self.orig_url)) @staticmethod def _flush_insert_event(mapper, connection, target): target._flush_event(mapper, connection, target) target.__flush_insert_event__(target)
class Post(CommentMixin, LikeMixin, CollectMixin, db.Model): __tablename__ = 'posts' author_id = db.Column(db.Integer) title = db.Column(db.String(128), default='') orig_url = db.Column(db.String(255), default='') can_comment = db.Column(db.Boolean, default=True) content = PropsItem() kind = K_POST __table_args__ = ( db.Index('idx_title', title), # noqa db.Index('idx_authorId', author_id)) def url(self): return '/{}/{}/'.format(self.__class__.__name__.lower(), self.id) @classmethod @cache(MC_KEY_GET_BY_TITLE % ('{title}')) def get_by_title(cls, title): return cls.query.filter_by(title=title).first() @classmethod def get(cls, identifier): return super().get(identifier) if is_numeric(identifier) \ else cls.get_by_title(identifier) @property @cache(MC_KEY_TAGS % ('{self.id}')) def tags(self): tag_ids = PostTag.query.with_entities(PostTag.tag_id).\ filter(PostTag.post_id == self.id).all() tags = Tag.query.filter(Tag.id.in_((id for id, in tag_ids))).all() return tags @cached_property def abstract_content(self): return trunc_utf8(self.content, 100) @cached_property def author(self): return User.get(self.author_id) @classmethod def create_or_update(cls, **kwargs): """ 给爬虫使用,创建post """ tags = kwargs.pop('tags', []) created, obj = super().create_or_update(**kwargs) if tags: PostTag.update_multi(obj.id, tags, []) if created: from handler.tasks import feed_post_to_followers feed_post_to_followers.delay(obj.id) return created, obj def update(self, **kwargs): rdb.delete(MC_KEY_GET_BY_TITLE % self.title) # 注意,在更新前清除缓存 super().update(**kwargs) def delete(self): super().delete() for pt in PostTag.query.filter_by(post_id=self.id): pt.delete() from handler.tasks import remove_post_from_feed remove_post_from_feed.delay(self.id, self.author_id) @cached_property def netloc(self): return urlparse(self.orig_url).netloc @classmethod def clear_mc(cls, target): rdb.delete(MC_KEY_GET_BY_TITLE % target.title) rdb.delete(MC_KEY_TAGS % target.id) @classmethod def __flush_delete_event__(cls, target): super().__flush_delete_event__(target) cls.clear_mc(target)