class UrlShorteningDailyCount(db.Model, BaseModel): __tablename__ = 'url_shortening_daily_count' date = db.Column(db.DateTime, nullable=False, index=True) success_count = db.Column(db.Integer, nullable=False, default=0) failed_count = db.Column(db.Integer, nullable=False, default=0) @classmethod def fetch_by_date(cls, date): return cls.custom_query().filter(cls.date == date)
class Journey(db.Model): id = db.Column(db.Integer, primary_key=True) people = db.Column(db.Integer, nullable=False, index=True) id_car = db.Column(db.Integer, db.ForeignKey('cars.id'), index=True) created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow) cars = relationship('Cars', back_populates='journey') __table_args__ = ( CheckConstraint('people >= 1'), CheckConstraint('people <= 6'), )
class Cars(db.Model): id = db.Column(db.Integer, primary_key=True) seats = db.Column(db.Integer, nullable=False, index=True) journey = relationship('Journey', back_populates='cars') __table_args__ = ( CheckConstraint('seats >= 4'), CheckConstraint('seats <= 6'), ) def __repr__(self): return 'Car {} has {} seats'.format(self.id, self.seats) def to_dict(self): return {'id': self.id, 'seats': self.seats}
class Shortner(db.Model, BaseModel): __tablename__ = 'shortner' long_url = db.Column(db.Text(), nullable=False) url_hash = db.Column(db.String(20), nullable=False, index=True) expires_at = db.Column(db.DateTime, nullable=False) hit_count = db.Column(db.Integer, nullable=False, default=0) delete_token = db.Column(db.String(100), nullable=False, default='NA') __table_args__ = (db.UniqueConstraint( 'url_hash', 'delete_token', name='uq_shortner_url_hash_delete_token'), ) @classmethod def fetch_by_hash(cls, hash_val): query = cls.custom_query().filter(cls.url_hash == hash_val) return query
class Seed(db.Model, BaseModel): __tablename__ = 'seeds' next_seed = db.Column(db.Integer, default=1) @classmethod def get_next_seed(cls): instance = cls.custom_query().with_for_update().first() if instance: next_seed = instance.next_seed instance.update(next_seed=next_seed+1, commit=True) else: next_seed = Default.ZOO_KEEPER_SEED cls.add(next_seed=next_seed, commit=True) return next_seed
class BaseModel: id = db.Column(db.Integer(), primary_key=True, autoincrement=True) created_at = db.Column( db.DateTime, default=datetime.utcnow, nullable=False ) created_by = db.Column(db.Integer(), nullable=True) updated_at = db.Column( db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False ) updated_by = db.Column(db.Integer(), nullable=True) deleted_at = db.Column(db.DateTime, nullable=True) @classmethod def custom_query(cls): return db.session.query(cls) def commit(self): try: db.session.add(self) db.session.commit() return self except IntegrityError: db.session.rollback() raise Exception("Integrity issue") except Exception: db.session.rollback() raise @classmethod def add(cls, **kwargs): obj = cls() obj.assign_attributes(**kwargs) obj.add_to_session() if kwargs.get('commit'): return obj.commit() return obj def update(self, **kwargs): self.assign_attributes(**kwargs) self.add_to_session() if kwargs.get('commit'): return self.commit() else: return self def assign_attributes(self, **kwargs): ignore_columns = ['id', 'createdAt', 'updatedAt', 'deletedAt'] for col_name in self.__table__.columns.keys(): if col_name not in ignore_columns and kwargs.get(col_name) is not None: setattr(self, col_name, kwargs.get(col_name)) return self def delete(self, commit=True): self.deleted_at = datetime.utcnow() if commit is True: return self.commit() else: return self def add_to_session(self): db.session.add(self) def to_dict(self): """ Dictionary representation of the object. By default all the columns are read, these can be extended by, setting an attribute `hybrid_properties` in the model and also can be filtered for sensitive fields using `hidden_fields` """ data = dict() hidden_fields = [] fields = self.__table__.columns.keys() if hasattr(self, 'hidden_fields'): hidden_fields = self.hidden_fields if hasattr(self, 'hybrid_properties'): fields += self.hybrid_properties for field in fields: if field not in hidden_fields: if hasattr(self, field): data[field] = getattr(self, field) if type(data[field]) == datetime: data[field] = str(data[field]) elif isinstance(data[field], BaseModel): data[field] = data[field].to_dict() return data
class User(db.Model, BaseModel, UserMixin): __tablename__ = 'users' first_name = db.Column(db.String(50), nullable=True) middle_name = db.Column(db.String(50), nullable=True) last_name = db.Column(db.String(50), nullable=True) username = db.Column(db.String(50), nullable=False) email = db.Column(db.String(50), nullable=False) primary_phone = db.Column(db.String(20), nullable=True) secret = db.Column(db.String(100), nullable=True) account_status = db.Column(db.String(50), nullable=False, default='active') password = db.Column(db.String(100), nullable=False) delete_token = db.Column(db.String(100), nullable=False, default='NA') roles = db.relationship('UserRole', backref='users') __table_args__ = ( db.UniqueConstraint('username', 'delete_token', name='uq_users_username_delete_token'), db.UniqueConstraint('email', 'delete_token', name='uq_users_email_delete_token'), ) def is_authenticated(self): return True def is_active(self): return True def is_anonymous(self): return False def get_id(self): return self.id def __repr__(self): return '<User %r>' % self.username @classmethod def add(cls, data, commit=True): user = cls() for col_name in user.__table__.columns.keys(): if col_name not in [ 'id', 'deleted', 'created_at', 'updated_at', 'deleted_at' ]: if col_name == 'password' and 'password' in data: secret = gen_salt(50) user.secret = secret user.password = cls.generate_password( data[col_name], secret) elif col_name == 'roles' and data[col_name]: for role in data[col_name]: UserRole.add(user=user, role_id=role, commit=False) elif col_name in data and data[col_name] is not None: setattr(user, col_name, data[col_name]) db.session.add(user) if commit: user.commit() return user @classmethod def generate_password(cls, password, salt): password_salt = password + salt return bcrypt.generate_password_hash( password_salt, rounds=current_app.config.get('BCRYPT_ROUNDS')) def check_password(self, candidate): """ Validate a candidate password with actual password """ candidate_salt = candidate + self.secret return bcrypt.check_password_hash(self.password, candidate_salt) @classmethod def fetch_by_username(cls, username): return cls.custom_query().filter(cls.username == username) @classmethod def fetch_by_user_id(cls, user_id): return cls.custom_query().filter(cls.id == user_id)