class Notification(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), index=True) user_id = db.Column(db.Integer, db.ForeignKey("users.id")) timestamp = db.Column(db.Float, index=True, default=time) payload_json = db.Column(db.Text) def get_data(self): return json.loads(str(self.payload_json))
class Message(db.Model): __tablename__ = "messages" id = db.Column(db.Integer, primary_key=True) sender_id = db.Column(db.Integer, db.ForeignKey("users.id")) recipient_id = db.Column(db.Integer, db.ForeignKey("users.id")) body = db.Column(db.String(140)) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) def __repr__(self): return f"<Message: {self.body}>"
class Post(SearchableMixin, db.Model): __tablename__ = "posts" __searchable__ = ["body"] id = db.Column(db.Integer, primary_key=True) body = db.Column(db.String(140)) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) user_id = db.Column(db.Integer, db.ForeignKey("users.id")) language = db.Column(db.String(5)) def __repr__(self): return f"<Post: {self.body}>"
class Task(db.Model): id = db.Column(db.String(36), primary_key=True) fname = db.Column(db.String(128), index=True) description = db.Column(db.String(128)) user_id = db.Column(db.Integer, db.ForeignKey("users.id")) complete = db.Column(db.Boolean, default=False) def get_rq_job(self): try: rq_job = rq.job.Job.fetch(self.id, connection=current_app.redis) except (redis.exceptions.RedisError, rq.exceptions.NoSuchJobError): return None return rq_job def get_progress(self): job = get_rq_job() return job.meta.get("progress", 0) if job is not None else 100
class User(UserMixin, db.Model): __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True) email = db.Column(db.String(120), unique=True) password_hash = db.Column(db.String(128)) posts = db.relationship("Post", backref="author", lazy="dynamic") about_me = db.Column(db.String(140)) last_seen = db.Column(db.DateTime, default=datetime.utcnow) followed = 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") messages_sent = db.relationship("Message", backref="author", lazy="dynamic", foreign_keys="Message.sender_id") messages_received = db.relationship("Message", backref="recipient", lazy="dynamic", foreign_keys="Message.recipient_id") last_message_read_time = db.Column(db.DateTime) notifications = db.relationship("Notification", backref="user", lazy="dynamic") tasks = db.relationship("Task", backref="user", lazy="dynamic") def set_password(self, password): self.password_hash = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password_hash, password) def avatar(self, size): digest = md5(self.email.lower().encode("utf-8")).hexdigest() return f"https://www.gravatar.com/avatar/{digest}?d=identicon&s={size}" def follow(self, user): if not self.is_following(user): self.followed.append(user) def unfollow(self, user): if self.is_following(user): self.followed.remove(user) def is_following(self, user): return self.followed.filter(followers.c.followed_id == user.id).count() > 0 def followed_posts(self): followedP = Post.query.join(followers, (followers.c.followed_id==Post.user_id)).filter(followers.c.follower_id==self.id) ownP = Post.query.filter_by(user_id=self.id) return followedP.union(ownP).order_by(Post.timestamp.desc()) def get_reset_password(self, expires_in=600): return jwt.encode({"reset_password": self.id, "exp": time() + expires_in}, current_app.config["SECRET_KEY"], algorithm="HS256").decode("utf-8") @staticmethod def verify_reset_password(token): try: id = jwt.decode(token, current_app.config["SECRET_KEY"], algorithm=["HS256"])["reset_password"] except: return return User.query.get(id) def new_messages(self): last_read_time = self.last_message_read_time or datetime(1900, 1, 1) return Message.query.filter_by(recipient=self).filter(Message.timestamp > last_read_time).count() 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 launch_task(self, fname, description, *args, **kwargs): rq_job = current_app.task_queue.enqueue("megatutApp.tasks."+fname, self.id, *args, **kwargs) task = Task(id=rq_job.get_id(), fname=fname, description=description, user=self) db.session.add(task) return task def get_tasks_in_progress(self): return Task.query.filter_by(user=self, complete=False).all() def get_task_in_progress(self, fname): return Task.query.filter_by(user=self, complete=False, fname=fname).first() def __repr__(self): return f"<Username: {self.username}>"
for obj in session._changes["add"]: add_to_index(cls.__tablename__, obj) for obj in session._changes["update"]: add_to_index(cls.__tablename__, obj) for obj in session._changes["delete"]: remove_from_index(cls.__tablename__, obj) session._changes = None @classmethod def reindex(cls): for obj in cls.query: add_to_index(cls.__tablename__, obj) followers = db.Table("followers", db.Column("follower_id", db.Integer, db.ForeignKey("users.id")), db.Column("followed_id", db.Integer, db.ForeignKey("users.id"))) class User(UserMixin, db.Model): __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True) email = db.Column(db.String(120), unique=True) password_hash = db.Column(db.String(128)) posts = db.relationship("Post", backref="author", lazy="dynamic") about_me = db.Column(db.String(140)) last_seen = db.Column(db.DateTime, default=datetime.utcnow) followed = 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") messages_sent = db.relationship("Message", backref="author", lazy="dynamic", foreign_keys="Message.sender_id") messages_received = db.relationship("Message", backref="recipient", lazy="dynamic", foreign_keys="Message.recipient_id")