Esempio n. 1
0
class Item(db.Model):
    # Columns for the table
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(length=30), nullable=False, unique=True)
    price = db.Column(db.Integer(), nullable=False)
    barcode = db.Column(db.String(length=12), nullable=False, unique=True)
    description = db.Column(db.String(length=1024),
                            nullable=False, unique=True)
    owner = db.Column(db.Integer(), db.ForeignKey('user.id'))

    def __repr__(self):
        return '<Item %r>' % self.id

    # Purchase the item
    def setOwnership(self, user):
        # Set ownership of the item to current user
        self.owner = user.id
        # Decrease the budget of the user
        user.budget -= self.price
        db.session.commit()

    # Sell the item
    def sell(self, user):
        # Set ownership to Nobody
        self.owner = None
        # Give the money back to the user
        user.budget += self.price
        db.session.commit()
Esempio n. 2
0
class User(db.Model):
    id = db.Column(db.Integer(), primary_key = True)
    username = db.Column(db.String(length = 20),nullable = False, unique = True)
    email_address = db.Column(db.String(length = 40), nullable = False, unique = True)
    password_hash = db.Column(db.String(length = 60), nullable = False)
    budget = db.Column(db.Integer(), nullable = False, default = 1000)
    items = db.relationship('Item', backref = 'owned_user', lazy = True)
Esempio n. 3
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email_address = db.Column(db.String(length=50),
                              nullable=False,
                              unique=True)
    password_hash = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    items = db.relationship('Item', backref='owned_user', lazy=True)

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        self.password_hash = bcrypt.generate_password_hash(
            plain_text_password).decode("utf-8")

    def check_password_correction(self, attempted_password):
        return bcrypt.check_password_hash(self.password_hash,
                                          attempted_password)

    def can_purchase(self, item_obj):
        return self.budget >= item_obj.price

    def can_sell(self, item_obj):
        return item_obj in self.items
Esempio n. 4
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(50), unique=True, nullable=False)
    password_hash = db.Column(db.String(100), nullable=False)
    name = db.Column(db.String(20), nullable=False)
    items = db.relationship('Item', backref='owned_user', lazy=True)
    budget = db.Column(db.Float(), nullable=False, default=1000.0)

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        self.password_hash = bcrypt.generate_password_hash(
            plain_text_password).decode('utf-8')

    def check_password_correction(self, attempted_password):
        return bcrypt.check_password_hash(self.password_hash,
                                          attempted_password)

    @property
    def prettier_budget(self):
        return "{:,}".format(self.budget) + " $"

    def __repr__(self):
        return f"{self.name}"
Esempio n. 5
0
class Item(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(length=30), nullable=False, unique=True)
    price = db.Column(db.Integer(), nullable=False)
    barcode = db.Column(db.String(length=12), nullable=False, unique=True)
    description = db.Column(db.String(length=1024),
                            nullable=False,
                            unique=True)
    owner = db.Column(db.Integer(), db.ForeignKey('user.id'))

    # To get the string representation of the database
    # Returns the name of the item
    def __repr__(self):
        return f'Item: {self.name}'

    #Function to assign ownership to a user
    def assign_owner(self, user_obj):
        self.owner = user_obj.id
        user_obj.budget -= self.price
        db.session.commit()

    #Function to change back ownership to market of the item
    def change_owner(self, user_obj):
        self.owner = None
        user_obj.budget += self.price
        db.session.commit()
Esempio n. 6
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(30), nullable=False, unique=True)
    email = db.Column(db.String(40), nullable=False, unique=True)
    password_hash = db.Column(db.String(40), nullable=False, unique=True)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    items = db.relationship('Item', backref='owned_user', lazy=True)

    @property
    def prettier_budget(self):
        return "${:,.2f}".format(self.budget)

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        self.password_hash = bcrypt.generate_password_hash(plain_text_password).decode('utf-8')

    def can_purchase(self, item_obj):
        return self.budget >=item_obj.price
    
    def can_sell(self, item_obj):
        return item_obj in self.items

    def __repr__(self):
        return f"User: {self.username}"
Esempio n. 7
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email_address = db.Column(db.String(length=50),
                              nullable=False,
                              unique=True)
    password_hash = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    items = db.relationship('Item', backref='owned_user', lazy=True)

    @property
    def prettier_budget(self):
        if len(str(self.budget)) >= 4:
            return f'{str(self.budget)[:-3]},{str(self.budget)[-3:]}$'
        else:
            return f'{self.budget}$'

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        self.password_hash = bcrypt.generate_password_hash(
            plain_text_password).decode('utf-8')

    def check_password_correction(self, attempted_password):
        return bcrypt.check_password_hash(self.password_hash,
                                          attempted_password)
Esempio n. 8
0
class Item(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(length=30), nullable=False, unique=True)
    price = db.Column(db.Integer(), nullable=False)
    barcode = db.Column(db.String(length=12), nullable=False, unique=True)
    description = db.Column(db.String(length=1024), nullable=False, unique=True)
    owner = db.Column(db.Integer(), db.ForeignKey('user.id'))

    def __repr__(self):
        return f'Item {self.name}'
Esempio n. 9
0
class Item(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(50), nullable=False)
    barcode = db.Column(db.String(50), nullable=False, unique=True)
    price = db.Column(db.Float(), nullable=False)
    description = db.Column(db.String(2000))
    owner = db.Column(db.Integer(), db.ForeignKey('user.id'))

    def __repr__(self):
        return f"{self.name}-{self.price}"
Esempio n. 10
0
class User(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email_address = db.Column(db.String(length=50),
                              nullable=False,
                              unique=True)
    password_hash = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    items = db.relationship("Item", backref="owned_user", lazy=True)

    def __repr__(self):
        return f"{self.name}"
Esempio n. 11
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=24), nullable=False, unique=True)
    email = db.Column(db.String(length=70), nullable=False, unique=True)
    hash_password = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=100000)
    items = db.relationship('Item', backref='owned_user', lazy=True)

    #To check if the user have enough budget to purchase the item
    def can_purchase(self, item_obj):
        return self.budget >= item_obj.price

    #To check if the user owns the item
    def can_sell(self, item_obj):
        return item_obj.owner == self.id

    # Returns the username of the User
    def __repr__(self):
        return self.username

    # Decorator property to return password to instances
    @property
    def password(self):
        return self.password

    # Decorator to execute code before we set a password
    @password.setter
    # plain_text_password is the filled in password
    def password(self, plain_text_password):
        # Assign hash_password field a hashed password generated from bcrypt instance
        self.hash_password = bcrypt.generate_password_hash(
            plain_text_password).decode('utf-8')

    def check_password_correction(self, attempted_password):
        return bcrypt.check_password_hash(self.hash_password,
                                          attempted_password)

    #To format the user budget
    @property
    def format_budget(self):
        temp_lis = list(str(self.budget))
        start = 2
        if len(temp_lis) > 3:
            if len(temp_lis) % 2 == 0:
                start = 1
            inc = 0
            for i in range(start, len(temp_lis) - 1, 2):
                temp_lis.insert(i + inc, ',')
                inc += 1
        return "₹" + "".join(temp_lis)
Esempio n. 12
0
class Item(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(length=30),nullable=False, unique=True)
    price = db.Column(db.Integer(),nullable=False)
    barcode = db.Column(db.String(length=12),nullable=False,unique=True)
    description = db.Column(db.String(length=1024),nullable=False,unique=True)
    owner = db.Column(db.Integer(), db.ForeignKey('user.id'))
    
    def buy(self, buying_user):
        self.owner = buying_user.id
        buying_user.budget -= self.price
        db.session.commit()
        
    def __repr__(self):
        return f'Item {self.name}'
Esempio n. 13
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(),primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email_address = db.Column(db.String(length=50), nullable=False, unique=True)
    password_hash = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    items = db.relationship("Item", backref="owned_user", lazy=True)

    def __repr__(self):
        return f"{self.username}"

    @property
    def prettier_budget(self):
        if len(str(self.budget)) == 4:
            n = self.budget
            b = []
            s = str(n)[::-1]
            b[0:] = s
            output = ""
            for i in range(1, len(s) + 1):
                if i % 3 == 0:
                    output += f"{s[i - 1]},"
                else:
                    output += s[i - 1]

            if output[::-1][0] == ",":
                return f"{output[::-1][1:]}$"
            else:
                return f'{output[::-1]}$'
        else:
            return f"{self.budget}$"

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        self.password_hash = bcrypt.generate_password_hash(plain_text_password).decode('utf-8')

    def check_password_correction(self, attempted_password):
        return bcrypt.check_password_hash(self.password_hash,attempted_password)

    def can_purchase(self, item_obj):
        return self.budget >= item_obj.price

    def can_sell(self, item_obj ):
        return item_obj in self.items
Esempio n. 14
0
class UpbitTradeHistory(db.Model):
    """ Price history 업비트의 체결 히스토리
    This records are used to generate indicators in the following:
    - Overlap Studies
    - Momentum Indicators
    """
    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    trade_date = db.Column(db.String)
    trade_time = db.Column(db.String)
    trade_timestamp = db.Column(db.DateTime)
    trade_price = db.Column(db.Integer)
    trade_volume = db.Column(db.Float)
    sequential_id = db.Column(db.BigInteger)
    ask_bid = db.Column(db.String(3))

    def __init__(self, obj):
        self.trade_date = obj["tradeDate"]
        self.trade_time = obj["tradeTime"]
        self.trade_timestamp = datetime.fromtimestamp(obj["timestamp"] / 1000)
        self.trade_price = obj["tradePrice"]
        self.trade_volume = obj["tradeVolume"]
        self.sequential_id = obj["sequentialId"]
        self.ask_bid = obj["askBid"]

    def _aslist(self):
        return [self.trade_timestamp.timestamp(), self.trade_price]
Esempio n. 15
0
class Item(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(length=30), nullable=False, unique=True)
    price = db.Column(db.Integer(), nullable=False)
    barcode = db.Column(db.String(length=12), nullable=False, unique=True)
    description = db.Column(db.String(length=1024), nullable=False, unique=True)
    owner = db.Column(db.Integer(), db.ForeignKey('user.id'))

    def buy(self, user):
        self.owner = user.id
        user.budget -= self.price
        db.session.commit()
    
    def sell(self,user):
        self.owner = None
        user.budget += self.price
        db.session.commit()
         
Esempio n. 16
0
class User(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email_address = db.Column(db.String(length=50),
                              nullable=False,
                              unique=True)
    password_hash = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    items = db.relationship('Item', backref='owned_user', lazy=True)

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        self.password_hash = bcrypt.generate_password_hash(
            plain_text_password).decode('utf-8')
Esempio n. 17
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email_address = db.Column(db.String(length=50),
                              nullable=False,
                              unique=True)
    password_hash = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    # this is the one that creates the relationship with the model, but is not stored as a column
    # backref is the field to relate to all the items the user has. Also to see the
    # owner of specific item
    # I need lazy=True to grab all the user's items in one shot
    items = db.relationship('Item', backref='owned_user', lazy=True)

    # property to format the budget
    @property
    def prettier_budget(self):
        if len(str(self.budget)) >= 4:
            return f'$ {str(self.budget)[:-3]},{str(self.budget)[-3:]}'
        else:
            return f"$ {self.budget}"

    # the next lines are for hashing the passwordjj
    # create an attribute that will be accesable from each instance.
    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        # overwrite what is going to be store in password_hash
        self.password_hash = bcrypt.generate_password_hash(
            plain_text_password).decode('utf-8')

    # to check if the psw is valid while login
    def check_password_correction(self, attempted_password):
        return bcrypt.check_password_hash(self.password_hash,
                                          attempted_password)

    def can_purchase(self, item_obj):
        return self.budget >= item_obj.price

    def can_sell(self, item_obj):
        return item_obj in self.items
Esempio n. 18
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(length=30), nullable=False, unique=True)
    email = db.Column(db.String(length=50), nullable=False, unique=True)
    password = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    items = db.relationship('Item', backref='owned_user', lazy=True)
    
    @property
    def prettier_budget(self):
        if len(str(self.budget)) >=4:
            return f'{str(self.budget)[:-3]},{str(self.budget)[-3:]}'
        else:
            return f'{self.budget}'

    def can_purchase(self, item_obj):
        return self.budget >= item_obj.price
    
    def can_sell(self,item_obj):
        return item_obj in self.items
Esempio n. 19
0
class Item(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(length=30), nullable=False, unique=True)
    price = db.Column(db.Integer(), nullable=False, unique=True)
    barcode = db.Column(db.String(length=12), nullable=False, unique=True)
    description = db.Column(db.String(1024), nullable=False, unique=True)
    # relationship to the user. 'user.id' must be in lower case
    owner = db.Column(db.Integer(), db.ForeignKey('user.id'))

    # I'm using this to return the value in name field
    def __repr__(self):
        return f'Item {self.name}'

    def buy(self, user):
        self.owner = user.id
        user.budget -= self.price
        db.session.commit()

    def sell(self, user):
        self.owner = None
        user.budget += self.price
        db.session.commit()
Esempio n. 20
0
class Agents(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), unique=True, nullable=False)
    cash = db.Column(db.Float, default=100000000)
    asset_qtys_currency = db.Column(db.String(100), default="KRW-BTC")
    asset_qtys = db.Column(db.Float, default=0.0)
    portfolio_rets_val = db.Column(db.Float, default=100000000)
    portfolio_rets_mdd = db.Column(db.Float, default=0.0)
    portfolio_rets_sharp = db.Column(db.Float, default=0.0)
    asset_qtys_zero_updated = db.Column(db.DateTime, default=datetime.utcnow)

    def __repr__(self):
        return "<Agent %r>" % self.name

    def _asdict(self):
        return dict(agent_info={
            "cash": self.cash,
            "asset_qtys": {
                self.asset_qtys_currency: self.asset_qtys
            }
        },
                    portfolio_rets={
                        "val": self.portfolio_rets_val,
                        "mdd": self.portfolio_rets_mdd,
                        "sharp": self.portfolio_rets_sharp
                    })

    def _asrank(self):
        cur_price = UpbitTradeHistory.query.order_by(
            desc(UpbitTradeHistory.trade_timestamp)).first().trade_price
        asset_val = round(self.asset_qtys * cur_price, Constants.BASE)
        portfolio_val = round(self.cash + asset_val, Constants.BASE)

        profit_ratio = ((portfolio_val / 100000000.0) - 1) * 100.0
        return dict(name=self.name,
                    cash=self.cash,
                    asset_qtys=self.asset_qtys,
                    portfolio_val=portfolio_val,
                    profit=int(profit_ratio * 10_000) / 10000.0)
Esempio n. 21
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email = db.Column(db.String(length=50), nullable=False, unique=True)
    password_hash = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1500)
    items = db.relationship('Item', backref='user', lazy=True)

    def __repr__(self):
        return self.username

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain):
        self.password_hash = bcrypt.generate_password_hash(plain).decode(
            'utf-8')

    def check_password(self, passc):
        return bcrypt.check_password_hash(self.password_hash, passc)
Esempio n. 22
0
class User(db.Model, UserMixin):
    # Columns for the table
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email_address = db.Column(db.String(length=50),
                              nullable=False, unique=True)
    password_hash = db.Column(db.String(length=60), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    items = db.relationship('Item', backref='owned_user', lazy=True)

    # We can define additional properties of our model like this
    @property
    # Puts a comma after thousands
    def prettier_budget(self):
        if len(str(self.budget)) >= 4:
            return f'₹{str(self.budget)[:-3]},{str(self.budget)[-3:]}'
        else:
            return f'₹{self.budget}'

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        self.password_hash = bcrypt.generate_password_hash(
            plain_text_password).decode('utf-8')

    def check_password_correction(self, attempted_password):
        return bcrypt.check_password_hash(self.password_hash, attempted_password)

    # Check if user can purchase the item
    def can_purchase(self, item_obj):
        return self.budget >= item_obj.price

    # Check if user can sell the item
    def can_sell(self, item_obj):
        return item_obj in self.items
Esempio n. 23
0
class User(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(length=30), nullable=False, unique=True)
    email = db.Column(db.String(length=50), nullable=False, unique=True)
    # hashed
    hashed_password = db.Column(db.String(length=50), nullable=False)
    budget = db.Column(db.Integer(), nullable=False, default=1000)
    # Relationship between two tables. User can own items.
    # owned_user would be an attribute in the 'Item' object
    # Lazy==true => items should be loaded lazily when the property is first accessed
    items = db.relationship('Item', backref='owned_user', lazy=True)

    # method used to represent a class’s objects as a string
    def __repr__(self):
        return f'User {self.username}'

    @property
    def password(self):
        return self.password

    @password.setter
    def password(self, plain_text_password):
        self.hashed_password = bcrypt.generate_password_hash(plain_text_password).decode('utf-8')
Esempio n. 24
0
class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=True)
    content = db.Column(db.Text, nullable=False)
    image = db.Column(db.String(20), nullable=False)
    image2 = db.Column(db.String(20), nullable=True)
    image3 = db.Column(db.String(20), nullable=True)
    price = db.Column(db.String(20), nullable=False)
    tags = db.Column(db.String(100), nullable=True)
    date_posted = db.Column(db.DateTime,
                            nullable=False,
                            default=datetime.utcnow)
    sold = db.Column(db.Boolean, default=False, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    likes = db.relationship('PostLike', backref='post', lazy='dynamic')
    comments = db.relationship("Comment",
                               backref="post",
                               lazy="dynamic",
                               cascade="all, delete-orphan")

    def __repr__(self):
        if self.title != None:
            return f"Post('{self.title}','{self.content}', '{self.date_posted}')"
        else:
            return f"Post({self.content}', '{self.date_posted}')"

    @staticmethod
    def on_changed_body(target, value, oldvalue, initiator):
        allowed_tags = [
            'a', 'abbr', 'acronym', 'b', 'blockquote', 'code', 'em', 'i', 'li',
            'ol', 'pre', 'strong', 'ul', 'h1', 'h2', 'h3', 'p', 'iframe'
        ]
        target.content = bleach.linkify(
            bleach.clean(markdown(value, output_format='html'),
                         tags=allowed_tags,
                         strip=True))
Esempio n. 25
0
class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    bio = db.Column(db.String(120), nullable=True)
    dp = db.Column(db.String(20), nullable=False, default='default.png')
    location = db.Column(db.String(50), nullable=True)
    contact = db.Column(db.String(50), nullable=True)
    password = db.Column(db.String(60), nullable=False)
    date_joined = db.Column(db.DateTime,
                            nullable=False,
                            default=datetime.utcnow)
    last_seen = db.Column(db.DateTime, default=datetime.utcnow)
    posts = db.relationship('Post', backref='author', lazy=True)
    comments = db.relationship("Comment",
                               backref="author",
                               lazy="dynamic",
                               cascade="all, delete-orphan")
    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',
                                    foreign_keys='Message.sender_id',
                                    backref='author',
                                    lazy='dynamic')
    messages_received = db.relationship('Message',
                                        foreign_keys='Message.recipient_id',
                                        backref='recipient',
                                        lazy='dynamic')
    last_message_read_time = db.Column(db.DateTime)

    def get_reset_token(self, expires_sec=1800):
        s = Serializer(app.config['SECRET_KEY'], expires_sec)
        return s.dumps({'user_id': self.id}).decode('utf-8')

    @staticmethod
    def verify_reset_token(token):
        s = Serializer(app.config['SECRET_KEY'])
        try:
            user_id = s.loads(token)['user_id']
        except:
            return None
        return User.query.get(user_id)

    def __repr__(self):
        return f"User('{self.username}' , '{self.email}', '{self.image_file}')"

    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):
        followed = Post.query.join(
            followers, (followers.c.followed_id == Post.user_id)).filter(
                followers.c.follower_id == self.id)
        own = Post.query.filter_by(user_id=self.id)
        return followed.union(own).order_by(Post.date_posted.desc())

    def like_post(self, post):
        if not self.has_liked_post(post):
            like = PostLike(user_id=self.id, post_id=post.id)
            db.session.add(like)

    def unlike_post(self, post):
        if self.has_liked_post(post):
            PostLike.query.filter_by(user_id=self.id, post_id=post.id).delete()

    def has_liked_post(self, post):
        return PostLike.query.filter(PostLike.user_id == self.id,
                                     PostLike.post_id == post.id).count() > 0

    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()

    @staticmethod
    def on_changed_body(target, value, oldvalue, initiator):
        allowed_tags = [
            'a', 'abbr', 'acronym', 'b', 'blockquote', 'code', 'em', 'i', 'li',
            'ol', 'pre', 'strong', 'ul', 'h3', 'p', 'iframe'
        ]
        target.content = bleach.linkify(
            bleach.clean(markdown(value, output_format='html'),
                         tags=allowed_tags,
                         strip=True))