class Album(db.Model): __tablename__ = "albums" id = db.Column(db.Integer(), primary_key=True) title = db.Column(db.String(255), nullable=False) artist = db.Column(db.String(255), nullable=False) description = db.Column(db.Text(), nullable=False) genre = db.Column(db.String(255), nullable=False) image = db.Column(db.Text(), nullable=False) release_date = db.Column(db.DateTime(), nullable=False) user_id = db.Column(db.Integer(), db.ForeignKey("users.id"), index=True, nullable=False) slug = db.Column(db.String(255), nullable=False, unique=True) def __init__(self, title, artist, description, genre, image, release_date, user_id): self.title = title self.artist = artist self.description = description self.genre = genre self.image = image self.release_date = release_date self.user_id = user_id
class Objective(db.Model): id = db.Column(db.Integer(), primary_key=True) title = db.Column(db.Text(), nullable=False) description = db.Column(db.Text(), default='') product_id = db.Column(db.Integer(), db.ForeignKey('product.id', ondelete='CASCADE'), index=True) targets = db.relationship('Target', backref=db.backref('objective', lazy='joined'), passive_deletes=True) username = db.Column(db.String(120), default='') created = db.Column(db.DateTime(), default=datetime.utcnow) updated = db.Column(db.DateTime(), onupdate=datetime.utcnow, default=datetime.utcnow) def get_owner(self): return self.product.product_group.name def __repr__(self): return '<SLO {} | {}>'.format(self.product.name, self.title)
class Ies(db.Model): __tablename__ = 'Ies' cod_ies = db.Column(db.INT(), primary_key=True) nome_ies = db.Column(db.Text()) sigla_ies = db.Column(db.Text()) num_cnpj = db.Column(db.BigInteger()) tipo_organizacao = db.Column(db.Text()) cod_mantenedora = db.Column(db.Integer()) email_ies = db.Column(db.Text()) site_ies = db.Column(db.Text())
class Movie(db.Model): __tablename__ = 'movie' id = db.Column(db.Integer, primary_key=True) img = db.Column(db.Text()) name = db.Column(db.String(64)) actor = db.Column(db.Text()) up_time = db.Column(db.DateTime()) score = db.Column(db.Float()) def __repr__(self): return '<User %r>' % self.name
class EntityType(db.Model, Timestamp): """ **EntityType** db model """ __tablename__ = 'entity_type' id = db.Column(db.String(length=60), unique=True, nullable=False, primary_key=True) name = db.Column(db.String(length=80), unique=True, nullable=False, default='') schema = db.Column(db.Text(), nullable=False) def __init__(self, **kwargs): self.id = uuid.uuid4().__str__() self.name = kwargs.get('name') self.schema = kwargs.get('schema') def json(self): data = dict([]) data['id'] = self.id data['name'] = self.name data['schema'] = self.schema return json.dumps(data)
class Channel(db.Model): __tablename__ = 'channels' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), unique=True, index=True) icon = db.Column(db.Text()) posts = db.relationship('Post', back_populates='channel', lazy='dynamic') @staticmethod def insert_channels(): channels = [ 'Python', 'JavaScript', 'dot-net', 'docker', 'Java', 'TypeScript', 'Vue.js' ] for i in channels: channel = Channel.query.filter_by(name=i).first() if channel: channel.icon = i.lower() else: channel = Channel() channel.name = i channel.icon = i.lower() db.session.add(channel) db.session.commit()
class Jobbrief(CRUD_Model, db.Model): __tablename__ = 'brief' id = db.Column(db.Integer, autoincrement=True, primary_key=True) key_word = db.Column(db.String(50)) job_name = db.Column(db.String(50)) job_location = db.Column(db.String(20)) job_salary_low = db.Column(db.Integer) job_salary_high= db.Column(db.Integer) job_exp = db.Column(db.Integer) job_edu = db.Column(db.String(20)) job_quantity = db.Column(db.String(20)) job_time = db.Column(db.DateTime()) job_other_require = db.Column(db.String(50)) job_labels = db.Column(db.Text()) #company = db.Column(db.String(50)) company_id = db.Column(db.Integer)####################### subscribe_id = db.Column(db.Integer)################# ''' company_id = db.Column(db.Integer, db.ForeignKey('company.id')) #下面这一个,在实际存储中,应当注意,在订阅中需要,非订阅中不需要, 每次对结果的存贮都需要判断 subscribe_id = db.Column(db.Integer, db.ForeignKey('subInfo.id')) job_link = db.relationship('Jobsite', back_populates='brief', lazy='dynamic') company = db.relationship('Company', back_populates='job', lazy=True) detail = db.relationship('Jobdetail', back_populates='abstract', lazy='dynamic') sub_info = db.relationship('Subscribe', back_populates='brief') ''' def __repr__(self): return '<object Jobbrief, id: {}, key_word: {}>'.format(self.id, self.key_word)
class Tour(db.Model): __tablename__ = "tours" id = db.Column(db.Integer(), primary_key=True) title = db.Column(db.String(255), nullable=False) artist = db.Column(db.String(255), nullable=False) description = db.Column(db.Text(), nullable=False) genre = db.Column(db.String(255), nullable=False) start_date = db.Column(db.DateTime(), nullable=False) end_date = db.Column(db.DateTime(), nullable=False) user_id = db.Column(db.Integer(), db.ForeignKey("users.id"), index=True, nullable=False) slug = db.Column(db.String(255), nullable=False, unique=True) def __init__(self, title, artist, description, genre, start_date, end_date, user_id): self.title = title self.artist = artist self.description = description self.genre = genre self.start_date = start_date self.end_date = end_date self.user_id = user_id
class Todo(db.Model, BaseModel): __tablename__ = 'todos' title = db.Column(db.String(500), nullable=False) content = db.Column(db.Text()) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) user = db.relationship('User', backref='todos', uselist=False) def __str__(self): return ('Id: {}, Title: {}'.format(self.id, self.title)) def to_dict(self): return { 'id': self.id, 'title': self.title, 'content': self.content } @classmethod def add(cls, title, content, user): """Add a Todo for a user Args: - title: str - content: str - user: User obj Returns: - Todo obj """ todo = cls(title=title, content=content, user=user) return todo.commit()
class User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64)) password = db.Column(db.String(128)) email = db.Column(db.String(100), unique=True) confirmed = db.Column(db.Boolean, nullable=False, default=False) confirmed_on = db.Column(db.DateTime, nullable=True) role = db.Column(db.Integer, index=True, default=UserRole.USER, nullable=False) location = db.Column(db.String(64)) description = db.Column(db.Text()) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow) def to_dict(self): return dict(id=self.id, username=self.username, email=self.email, confirmed=self.confirmed, role=self.role)
class Post(CRUD_Model, db.Model): __tablename__ = 'post' id = db.Column(db.Integer, autoincrement=True, primary_key=True) title = db.Column(db.String(50), nullable=False) post = db.Column(db.Text(), nullable=False) post_time = db.Column(db.DateTime(), default=datetime.now()) labels = db.Column(db.Text()) author_id = db.Column(db.Integer)################ ''' author_id = db.Column(db.Integer, db.ForeignKey('user.id')) author = db.relationship('User', back_populates='posts', lazy=True) comment = db.relationship('Comment', back_populates='post', lazy='dynamic') ''' def __repr__(self): return '<object Post, id: {}>'.format(self.id)
class Comment(db.Model): __tablename__ = "comments" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255), nullable=False) text = db.Column(db.Text()) date = db.Column(db.DateTime()) post_id = db.Column(db.Integer, db.ForeignKey('posts.id')) def __repr__(self): return "<Model Comment {}>".format(self.name)
class Basket(db.Model): "A basket of foos." __tablename__ = 'basket' id = db.Column('id', db.Integer(), primary_key=True) name = db.Column('name', db.Text(), nullable=False) created_ts = db.Column(db.DateTime(timezone=True), server_default=text('NOW()')) foos = db.relationship('Foo', backref='basket', lazy='dynamic')
class Post(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(80)) content = db.Column(db.Text()) def __init__(self, title, content): self.title = title self.content = content def __repr__(self): return '<Post %r>' % self.title
class Foo(db.Model): "A foo." __tablename__ = 'foo' id = db.Column('id', db.Integer(), primary_key=True) bar = db.Column('bar', db.Integer(), nullable=False) baz = db.Column('baz', db.Text(), nullable=False) created_ts = db.Column(db.DateTime(timezone=True), server_default=text('NOW()')) basket_id = db.Column(db.Integer, db.ForeignKey('basket.id'))
class Jobdetail(CRUD_Model, db.Model): __tablename__ = 'requirement' id = db.Column(db.Integer, autoincrement=True, primary_key=True) requirement = db.Column(db.Text()) brief_id = db.Column(db.Integer)######################### ''' brief_id = db.Column(db.Integer, db.ForeignKey('brief.id')) abstract = db.relationship('Jobbrief', back_populates='detail') ''' def __repr__(self): return '<object Jobdetail, id: {}>'.format(self.id)
class Channels(db.Model): """ 渠道表 """ __tablename__ = "t_channels" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(length=30), unique=True) remark = db.Column(db.Text(length=500)) # zones = db.relationship("Zones", backref='channel', lazy="dynamic") def __repr__(self): return '<Channel {}>'.format(self.name)
class Exorder(db.Model): __tablename__ = 'exorder' sorderid = db.Column(db.String(64), primary_key=True, default=str(uuid1())) orderid = db.Column(db.String(64), nullable=False) sellerid = db.Column(db.String(64), nullable=False) userid = db.Column(db.String(64), nullable=False) exdesc = db.Column(db.String(64)) exrepl = db.Column(db.Text(128)) createtime = db.Column(db.DateTime, default=str(datetime.now())) repltime = db.Column(db.DateTime, default=str(datetime.now())) def db2json(self): data = to_json(self) return data
class User(db.Model, UserMixin): #实例化USER模型 __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(20)) password_hash = db.Column(db.String(128)) name = db.Column(db.String(30)) about = db.Column(db.Text(128)) def set_password(self, password): self.password_hash = generate_password_hash(password) def vaildata_password(self, password): return check_password_hash(self.password_hash, password)
class Post(db.Model): __tablename__ = "posts" id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(255)) text = db.Column(db.Text()) publish_date = db.Column(db.DateTime) #设置外键 user_id = db.Column(db.Integer, db.ForeignKey('users.id')) comments = db.relationship('Comment', backref="posts", lazy="dynamic") tags = db.relationship('Tag', secondary=posts_tags, backref=db.backref('posts', lazy='dynamic')) def __repr__(self): return "<Model Post {}>".format(self.title)
class Article(db.Model): __tablename__ = 'articles' default_image = "https://premar.tech/site/wp-content/uploads/2019/01/cropped-premar3_512x512-3.jpg" id = db.Column(db.Integer, db.Sequence('articles_id_seq'), primary_key=True, autoincrement=True) name = db.Column(db.String(120), unique=True) link = db.Column(db.Text()) image = db.Column(db.Text()) summary = db.Column(db.Text()) def __init__(self, name=None, link=None, image=default_image, summary=None): self.name = name self.link = link self.image = image self.summary = summary def __repr__(self): return "<User(id=%d, name='%s', link='%s', image='%s', summary='%s')>" % \ (self.id, self.name, self.link, self.image, self.summary) def to_dict(self): return { 'id': self.id, 'name': self.name, 'link': self.link, 'image': self.image, 'summary': self.summary }
class Entity(db.Model, Timestamp): """ **Entity** db model """ __tablename__ = 'entity' id = db.Column(db.String(length=60), unique=True, nullable=False, primary_key=True, default=uuid.uuid4().__str__) entityTypeId = db.Column(db.String(length=60), db.ForeignKey('entity_type.id'), nullable=False) content = db.Column(db.Text(), nullable=False)
class Image(db.Model): """Class to represent an image""" __tablename__ = "images" id = db.Column(db.Integer, primary_key=True) path = db.Column(db.Text(), unique=True, index=True, nullable=False) uploaded_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) image_type_id = db.Column(db.Integer, db.ForeignKey("image_types.id"), nullable=False) event_id = db.Column(db.Integer, db.ForeignKey("events.id"), nullable=False) def __repr__(self): """Return a string representation of the Image class. Used for debugging purposes """ return "<Image at: %r>" % self.path
class Goods(db.Model): __tablename__ = 'goods' goodsid = db.Column(db.String(64), primary_key=True, default=str(uuid1())) menuid = db.Column(db.String(64), nullable=False) sellerid = db.Column(db.String(64), nullable=False) goodsname = db.Column(db.String(64), nullable=False) count = db.Column(db.Integer, nullable=False) price = db.Column(db.DECIMAL(10, 2), nullable=False) spic = db.Column(db.String(64), nullable=False) bpic = db.Column(db.String(64), nullable=False) unit = db.Column(db.String(32), nullable=False) online = db.Column(db.String(2), default='1') isfirstpageshow = db.Column(db.String(2), default='1') isshow = db.Column(db.String(2), default='1') selpoint = db.Column(db.Text(128)) delflag = db.Column(db.String(2), default='0') createtime = db.Column(db.DateTime, default=str(datetime.now())) updatetime = db.Column(db.DateTime, default=str(datetime.now())) def db2json(self): data = to_json(self) return data
class EntityAudit(db.Model, Timestamp): """ **Entity Audit** db model """ __tablename__ = 'entity_audit' id = db.Column(db.String(length=60), unique=True, nullable=False, primary_key=True, default=uuid.uuid4().__str__) updatedEntityId = db.Column(db.String(length=60), db.ForeignKey('entity.id'), nullable=False) action = db.Column(db.String(length=20), nullable=False) originalEntityContent = db.Column(db.Text(), nullable=False) changedByEntityId = db.Column(db.String(length=60), db.ForeignKey('entity.id'), nullable=False)
class AppleSubscription(db.Model, ModelMixin): """ For users who have subscribed via Apple in-app payment """ user_id = db.Column( db.ForeignKey(User.id, ondelete="cascade"), nullable=False, unique=True ) expires_date = db.Column(ArrowType, nullable=False) # to avoid using "Restore Purchase" on another account original_transaction_id = db.Column(db.String(256), nullable=False, unique=True) receipt_data = db.Column(db.Text(), nullable=False) plan = db.Column(db.Enum(PlanEnum), nullable=False) user = db.relationship(User) def is_valid(self): # Todo: take into account grace period? return self.expires_date > arrow.now().shift(days=-_APPLE_GRACE_PERIOD_DAYS)
class Question(db.Model): __tablename__ = 'questions' id = db.Column(db.Integer, primary_key=True) text = db.Column(db.Text(256), nullable=False) creationDate = db.Column(db.DateTime, default=datetime.utcnow) username = db.Column(db.String(120), nullable=False) answers = db.relationship('Answer', backref='question', lazy=False) def to_json(self): json = { 'id': self.id, 'text': self.text, 'user': self.username, 'creationDate': self.creationDate.strftime('%Y-%m-%d %H:%M:%S'), 'answers': [item.to_json() for item in self.answers], 'answersQty': len(self.answers), } return json @classmethod def create(cls, **kwargs: Dict[str, str]): text = kwargs.get('text', '') username = kwargs.get('username', '') item = cls(text=text, username=username) return item def save(self): db.session.add(self) db.session.commit() @classmethod def get_questions_list(cls): result = cls.query.order_by(desc(cls.creationDate)).all() return result
class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, db.Sequence('user_id_seq'), primary_key=True, autoincrement=True) username = db.Column(db.String(100), unique=True) name = db.Column(db.String(150)) password = db.Column(db.String(191)) embeddings = db.Column(db.Text()) def __init__(self, username=None, password=None, name=None, embeddings=None): self.username = username self.name = name self.embeddings = embeddings self.password = generate_password_hash(password) def __repr__(self): return "<User(id=%d, username='******', name='%s', password='******', embeddings='%s')>" % \ (self.id, self.username, self.name, self.password, self.embeddings) def to_dict(self): return { 'id': self.id, 'username': self.username, 'name': self.name, 'password': self.password, 'embeddings': self.embeddings } # some comment def check_password(self, password): return check_password_hash(self.password, password)
class User(PaginatedAPIMixin, db.Model): # 设置数据库表名,Post模型中的外键 user_id 会引用 users.id __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), index=True, unique=True) email = db.Column(db.String(120), index=True, unique=True) password_hash = db.Column(db.String(128)) # 不保存原始密码 name = db.Column(db.String(64)) location = db.Column(db.String(64)) about_me = db.Column(db.Text()) member_since = db.Column(db.DateTime(), default=datetime.utcnow) last_seen = db.Column(db.DateTime(), default=datetime.utcnow) # 反向引用,直接查询出当前用户的所有博客文章; 同时,Post实例中会有 author 属性 # cascade 用于级联删除,当删除user时,该user下面的所有posts都会被级联删除 posts = db.relationship('Post', backref='author', lazy='dynamic', cascade='all, delete-orphan') diaries = db.relationship('Diary', backref='author', lazy='dynamic', cascade='all, delete-orphan') # followeds 是该用户关注了哪些用户列表 # followers 是该用户的粉丝列表 followeds = db.relationship('User', secondary=followers, primaryjoin=(followers.c.follower_id == id), secondaryjoin=(followers.c.followed_id == id), backref=db.backref('followers', lazy='dynamic'), lazy='dynamic') # 用户发表的评论列表 comments = db.relationship('Comment', backref='author', lazy='dynamic', cascade='all, delete-orphan') # 用户最后一次查看 收到的评论 页面的时间,用来判断哪些收到的评论是新的 last_recived_comments_read_time = db.Column(db.DateTime) # 用户最后一次查看 用户的粉丝 页面的时间,用来判断哪些粉丝是新的 last_follows_read_time = db.Column(db.DateTime) # 用户最后一次查看 收到的文章被喜欢 页面的时间,用来判断哪些喜欢是新的 last_posts_likes_read_time = db.Column(db.DateTime) # 用户最后一次查看 收到的评论点赞 页面的时间,用来判断哪些点赞是新的 last_comments_likes_read_time = db.Column(db.DateTime) # 用户最后一次查看 关注的人的博客 页面的时间,用来判断哪些文章是新的 last_followeds_posts_read_time = db.Column(db.DateTime) # 用户的通知 notifications = db.relationship('Notification', backref='user', lazy='dynamic', cascade='all, delete-orphan') # 用户发送的私信 messages_sent = db.relationship('Message', foreign_keys='Message.sender_id', backref='sender', lazy='dynamic', cascade='all, delete-orphan') # 用户接收的私信 messages_received = db.relationship('Message', foreign_keys='Message.recipient_id', backref='recipient', lazy='dynamic', cascade='all, delete-orphan') # 用户最后一次查看私信的时间 last_messages_read_time = db.Column(db.DateTime) # harassers 骚扰者(被拉黑的人) # sufferers 受害者 harassers = db.relationship('User', secondary=blacklist, primaryjoin=(blacklist.c.user_id == id), secondaryjoin=(blacklist.c.block_id == id), backref=db.backref('sufferers', lazy='dynamic'), lazy='dynamic') # 用户注册后,需要先确认邮箱 confirmed = db.Column(db.Boolean, default=False) # 用户所属的角色 role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) # 用户的RQ后台任务 tasks = db.relationship('Task', backref='user', lazy='dynamic') def set_password(self, password): """设置用户密码,保存为 Hash 值""" self.password_hash = generate_password_hash(password) def check_password(self, password): """验证密码与保存的 Hash 值是否匹配""" return check_password_hash(self.password_hash, password) def avatar(self, size): """用户头像""" if self.email: digest = md5(self.email.lower().encode('utf-8')).hexdigest() return 'https://www.gravatar.com/avatar/{}?d=identicon&s={}'.format( digest, size) def to_dict(self, include_email=False): data = { 'id': self.id, 'username': self.username, 'name': self.name, 'location': self.location, 'about_me': self.about_me, 'member_since': self.member_since.isoformat() + 'Z', 'last_seen': self.last_seen.isoformat() + 'Z', 'followeds_count': self.followeds.count(), 'followers_count': self.followers.count(), 'posts_count': self.posts.count(), 'diaries_count': self.diaries.count(), 'followeds_posts_count': self.followeds_posts().count(), 'comments_count': self.comments.count(), 'confirmed': self.confirmed, 'role_id': self.role_id, 'role_name': Role.query.get_or_404(self.role_id).name, '_links': { 'self': url_for('api.get_user', id=self.id), 'avatar': self.avatar(128), 'followeds': url_for('api.get_followeds', id=self.id), 'followers': url_for('api.get_followers', id=self.id), 'posts': url_for('api.get_user_posts', id=self.id), 'diaries': url_for('api.get_diaries', id=self.id), 'followeds_posts': url_for('api.get_user_followeds_posts', id=self.id), 'comments': url_for('api.get_user_comments', id=self.id), 'role': url_for('api.get_role', id=self.role_id) } } if include_email: data['email'] = self.email return data def from_dict(self, data, new_user=False): for field in [ 'username', 'email', 'name', 'location', 'about_me', 'confirmed', 'role_id' ]: if field in data: setattr(self, field, data[field]) if new_user and 'password' in data: self.set_password(data['password']) # 新建用户时,给用户自动分配角色 if self.role is None: if self.email in current_app.config['ADMINS']: self.role = Role.query.filter_by( slug='administrator').first() else: self.role = Role.query.filter_by(default=True).first() def ping(self): """更新用户的最后访问时间""" self.last_seen = datetime.utcnow() db.session.add(self) def get_jwt(self, expires_in=10080): """用户登录后,发放有效的 JWT""" now = datetime.utcnow() payload = { 'user_id': self.id, 'confirmed': self.confirmed, 'user_name': self.name if self.name else self.username, 'user_avatar': base64.b64encode(self.avatar(24).encode('utf-8')).decode('utf-8'), 'permissions': self.role.get_permissions(), 'exp': now + timedelta(seconds=expires_in), 'iat': now } return jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256').decode('utf-8') @staticmethod def verify_jwt(token): """验证 JWT 的有效性""" try: payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256']) except (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidSignatureError, jwt.exceptions.DecodeError) as e: # Token过期,或被人修改,那么签名验证也会失败 return None return User.query.get(payload.get('user_id')) def is_following(self, user): """判断当前用户是否已经关注了 user 这个用户对象,如果关注了,下面表达式左边是1,否则是0""" return self.followeds.filter( followers.c.followed_id == user.id).count() > 0 def follow(self, user): """当前用户开始关注 user 这个用户对象""" if not self.is_following(user): self.followeds.append(user) def unfollow(self, user): """当前用户取消关注 user 这个用户对象""" if self.is_following(user): self.followeds.remove(user) def followeds_posts(self): '''获取当前用户的关注者的所有博客列表''' followed = Post.query.join( followers, (followers.c.followed_id == Post.author_id)).filter( followers.c.follower_id == self.id) # 包含当前用户自己的博客列表 # own = Post.query.filter_by(user_id=self.id) # return followed.union(own).order_by(Post.timestamp.desc()) return followed.order_by(Post.timestamp.desc()) def add_notification(self, name, data): '''给用户实例对象增加通知''' # 如果具有相同名称的通知已存在,则先删除该通知 self.notifications.filter_by(name=name).delete() # 为用户添加通知,写入数据库 n = Notification(name=name, payload_json=json.dumps(data), user=self) db.session.add(n) return n def new_recived_comments(self): '''用户收到的新评论计数 包括: 1. 用户的所有文章下面新增的评论 2. 用户发表的评论(或下面的子孙)被人回复了 ''' last_read_time = self.last_recived_comments_read_time or datetime( 1900, 1, 1) # 用户发布的所有文章 user_posts_ids = [post.id for post in self.posts.all()] # 用户文章下面的新评论, 即评论的 post_id 在 user_posts_ids 集合中,且评论的 author 不是自己(文章的作者) q1 = set( Comment.query.filter(Comment.post_id.in_(user_posts_ids), Comment.author != self).all()) # 用户发表的评论被人回复了,找到每个用户评论的所有子孙 q2 = set() for c in self.comments: q2 = q2 | c.get_descendants() q2 = q2 - set(self.comments.all() ) # 除去子孙中,用户自己发的(因为是多级评论,用户可能还会在子孙中盖楼),自己回复的不用通知 # 用户收到的总评论集合为 q1 与 q2 的并集 recived_comments = q1 | q2 # 最后,再过滤掉 last_read_time 之前的评论 return len( [c for c in recived_comments if c.timestamp > last_read_time]) def new_follows(self): '''用户的新粉丝计数''' last_read_time = self.last_follows_read_time or datetime(1900, 1, 1) return self.followers.filter( followers.c.timestamp > last_read_time).count() def new_comments_likes(self): """用户收到的新评论点赞计数""" last_read_time = self.last_comments_likes_read_time or datetime( 1900, 1, 1) # 当前用户发表的所有评论当中,哪些被点赞了 comments = self.comments.join(comments_likes).all() # 新的点赞记录计数 new_likes_count = 0 for c in comments: # 获取点赞时间 for u in c.likers: if u != self: # 用户自己点赞自己的评论不需要被通知 res = db.engine.execute( "select * from comments_likes where user_id={} and comment_id={}" .format(u.id, c.id)) timestamp = datetime.strptime( list(res)[0][2], '%Y-%m-%d %H:%M:%S.%f') # 判断本条点赞记录是否为新的 if timestamp > last_read_time: new_likes_count += 1 return new_likes_count def new_followeds_posts(self): """用户关注的人的新发布的文章计数""" last_read_time = self.last_followeds_posts_read_time or datetime( 1900, 1, 1) return self.followeds_posts().filter( Post.timestamp > last_read_time).count() def new_recived_messages(self): """用户未读的私信计数""" last_read_time = self.last_messages_read_time or datetime(1900, 1, 1) return Message.query.filter_by(recipient=self).filter( Message.timestamp > last_read_time).count() def is_blocking(self, user): """判断当前用户是否已经拉黑了 user 这个用户对象,如果拉黑了,下面表达式左边是1,否则是0""" return self.harassers.filter( blacklist.c.block_id == user.id).count() > 0 def block(self, user): '''当前用户开始拉黑 user 这个用户对象''' if not self.is_blocking(user): self.harassers.append(user) def unblock(self, user): '''当前用户取消拉黑 user 这个用户对象''' if self.is_blocking(user): self.harassers.remove(user) def new_posts_likes(self): '''用户收到的文章被喜欢的新计数''' last_read_time = self.last_posts_likes_read_time or datetime( 1900, 1, 1) # 当前用户发布的文章当中,哪些文章被喜欢了 posts = self.posts.join(posts_likes).all() # 新的喜欢记录计数 new_likes_count = 0 for p in posts: # 获取喜欢时间 for u in p.likers: if u != self: # 用户自己喜欢自己的文章不需要被通知 res = db.engine.execute( "select * from posts_likes where user_id={} and post_id={}" .format(u.id, p.id)) timestamp = datetime.strptime( list(res)[0][2], '%Y-%m-%d %H:%M:%S.%f') # 判断本条喜欢记录是否为新的 if timestamp > last_read_time: new_likes_count += 1 return new_likes_count def generate_confirm_jwt(self, expires_in=3600): '''生成确认账户的 JWT''' now = datetime.utcnow() payload = { 'confirm': self.id, 'exp': now + timedelta(seconds=expires_in), 'iat': now } return jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256').decode('utf-8') def verify_confirm_jwt(self, token): '''用户点击确认邮件中的URL后,需要检验 JWT,如果检验通过,则把新添加的 confirmed 属性设为 True''' try: payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256']) except (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidSignatureError, jwt.exceptions.DecodeError) as e: # Token过期,或被人修改,那么签名验证也会失败 return False if payload.get('confirm') != self.id: return False self.confirmed = True db.session.add(self) return True def generate_reset_password_jwt(self, expires_in=3600): '''生成重置账户密码的 JWT''' now = datetime.utcnow() payload = { 'reset_password': self.id, 'exp': now + timedelta(seconds=expires_in), 'iat': now } return jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256').decode('utf-8') @staticmethod def verify_reset_password_jwt(token): '''用户点击重置密码邮件中的URL后,需要检验 JWT 如果检验通过,则返回 JWT 中存储的 id 所对应的用户实例''' try: payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256']) except (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidSignatureError, jwt.exceptions.DecodeError) as e: # Token过期,或被人修改,那么签名验证也会失败 return None return User.query.get(payload.get('reset_password')) def can(self, perm): '''检查用户是否有指定的权限''' return self.role is not None and self.role.has_permission(perm) def is_administrator(self): '''检查用户是否为管理员''' return self.can(Permission.ADMIN) def get_task_in_progress(self, name): '''检查指定任务名的RQ任务是否还在运行中''' return Task.query.filter_by(name=name, user=self, complete=False).first() def launch_task(self, name, description, *args, **kwargs): '''用户启动一个新的后台任务''' rq_job = current_app.task_queue.enqueue('app.utils.tasks.' + name, *args, **kwargs) task = Task(id=rq_job.get_id(), name=name, description=description, user=self) db.session.add(task) db.session.commit() return task def get_tasks_in_progress(self): """返回用户所有正在运行中的后台任务""" return Task.query.filter_by(user=self, complete=False).all() def __repr__(self): return '<User {}>'.format(self.username)
class Email(ResourceMixin, db.Model): __tablename__ = 'emails' # Relationships. user_id = db.Column(db.Integer, db.ForeignKey('users.id', onupdate='CASCADE', ondelete='CASCADE'), index=True, nullable=False) # Parsed objects. message_id = db.Column(db.String(255), unique=False, index=True, nullable=True, server_default='') from_ = db.Column(db.String(255), unique=False, index=True, nullable=True, server_default='') to = db.Column(db.String(255), unique=False, index=True, nullable=True, server_default='') subject = db.Column(db.String(255), unique=False, index=True, nullable=True, server_default='') date = db.Column(db.String(255), unique=False, index=True, nullable=True, server_default='') body = db.Column(db.Text(), unique=False, index=True, nullable=True, server_default='') def __init__(self, **kwargs): # Call Flask-SQLAlchemy's constructor. super(Email, self).__init__(**kwargs) @classmethod def find_by_id(cls, identity): """ Find an email by its message id. :param identity: Email or username :type identity: str :return: User instance """ return Email.query.filter( (Email.message_id == identity).first()) @classmethod def search(cls, query): """ Search a resource by 1 or more fields. :param query: Search query :type query: str :return: SQLAlchemy filter """ if not query: return '' search_query = '%{0}%'.format(query) search_chain = (Email.message_id.ilike(search_query)) return or_(*search_chain) @classmethod def get_all_emails(cls, ids): """ Return all emails that are stored in the database :param ids: List of ids to be returned :type ids: list :return: list of emails """ emails = [] for id in ids: email = Email.query.get(id) if email is None: continue emails.append(email) return emails @classmethod def bulk_delete(cls, ids): """ Override the general bulk_delete method because we need to delete them one at a time while also deleting them on Stripe. :param ids: List of ids to be deleted :type ids: list :return: int """ delete_count = 0 for id in ids: email = Email.query.get(id) if email is None: continue email.delete() delete_count += 1 return delete_count