class ReturnTime(db.Model): __tablename__ = "return_time" id = db.Column(db.Integer, primary_key=True) accepted_return_time = db.Column(db.DateTime, nullable=False) location = db.Column(db.String(120), nullable=False) request_id = db.Column(db.Integer, db.ForeignKey('return_request.id')) request = db.relationship( 'ReturnRequest', backref=db.backref( 'will_be_returned_on', lazy='dynamic', cascade="all, delete-orphan", ), ) def __init__(self, return_time, request, location): self.accepted_return_time = return_time self.request = request self.location = location def confirmReturned(self): # The item should be marked as available again. tx = self.request.transaction tx.is_complete = True tx.is_with_rentee = False tx.listed_item.is_available = True # All return request objects should be deleted. db.session.delete(self.request) db.session.commit() return True def __repr__(self): tx = self.request.transaction item = tx.listed_item return "{0} will return {1}'s {2} on {3} at {4}".format( tx.rentee.username, item.owner.username, item.item_type.name, self.accepted_return_time, self.location, )
class BlogCategory(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(128), unique=True) slug = db.Column(db.String(128), unique=True, index=True) order = db.Column(db.SmallInteger, default=0) description = db.Column(db.Text, nullable=True) parent_id = db.Column(db.Integer, db.ForeignKey('blog_category.id'), index=True) parent = db.relationship(lambda: BlogCategory, remote_side=id, backref=db.backref('sub_categories', lazy='dynamic')) __mapper_args__ = {'order_by': order} def __repr__(self): return '%s' % self.title
class ProposedReturnTime(db.Model): __tablename__ = "proposed_return_time" id = db.Column(db.Integer, primary_key=True) location = db.Column(db.String(80), nullable=False) proposed_timestamp = db.Column(db.DateTime, nullable=False) can_pickup_until = db.Column(db.DateTime, nullable=False) request_id = db.Column(db.Integer, db.ForeignKey('return_request.id')) request = db.relationship( 'ReturnRequest', backref=db.backref('times_to_return', lazy='dynamic', cascade="all, delete-orphan"), ) def __init__(self, start, stop, request, location): self.location = location self.proposed_timestamp = start self.can_pickup_until = stop self.request = request def returnOn(self, return_time): r = ReturnTime( return_time=return_time, request=self.request, location=self.location, ) return r def __repr__(self): tx = self.request.transaction item = tx.listed_item return ("{0} is available to recieve {1} from {2}" " between {3} and {4} at {5}".format( item.owner.username, item.item_type.name, tx.rentee.username, self.proposed_timestamp, self.can_pickup_until, self.location, ))
class BlogPost(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(128), unique=True) slug = db.Column(db.String(128), unique=True, index=True) content = db.Column(db.Text()) created = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) modified = db.Column(db.DateTime, server_default=db.func.now()) category_id = db.Column(db.Integer, db.ForeignKey('blog_category.id'), index=True) category = db.relationship(lambda: BlogCategory, backref=db.backref('posts', lazy='dynamic')) excerpt = db.Column(db.Text, nullable=True) tags = db.Column(ARRAY(db.String(64)), nullable=True, index=True) def __repr__(self): return self.title
class User(db.Model, UserMixin): id = db.Column(db.Integer, unique=True, primary_key=True) username = db.Column(db.String(20), unique=True, nullable=False) first_name = db.Column(db.String(20)) last_name = db.Column(db.String(20)) gender = db.Column(db.String(20)) birth_date = db.Column(db.Date()) email = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(60), nullable=False) image_file = db.Column(db.String(30)) bio = db.Column(db.String(240)) travels = db.relationship('Travel', backref='traveler', lazy='dynamic', cascade='all, delete-orphan', passive_deletes=True) followed = db.relationship('Follow', foreign_keys=[Follow.follower_id], backref=db.backref('follower', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan', passive_deletes=True) followers = db.relationship('Follow', foreign_keys=[Follow.followed_id], backref=db.backref('followed', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan', passive_deletes=True) subscribed_travels = db.relationship('Subscribe', backref=db.backref('subscriber', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan', passive_deletes=True) def __repr__(self): return f"User('{self.username}', '{self.email}', '{self.image_file}')" def to_json(self): json_user = { 'id': self.id, 'username': self.username, 'followers': len(self.followers.all()), 'followed': len(self.followed.all()), 'subscribed_travels': len(self.subscribed_travels.all()), 'bio': self.bio, 'first_name': self.first_name, 'last_name': self.last_name } return json_user def get_posts_as_list(self): userPosts = [i.to_json() for i in self.travels] return userPosts def get_posts_as_list_with_sub(self, other_user): userPosts = [ i.to_json_with_sub_check(other_user) for i in self.travels ] return userPosts def getfollowers(self): userfollowers = [i.to_json() for i in self.followers] return userfollowers def getfollowings(self): userfollowed = [i.to_json() for i in self.followed] return userfollowed
class Travel(db.Model): id = db.Column(db.Integer, primary_key=True, unique=True) title = db.Column(db.Text, nullable=False) date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False) start_date = db.Column(db.DateTime, nullable=False) end_date = db.Column(db.DateTime, nullable=False) country = db.Column(db.Text, nullable=False) city = db.Column(db.Text, nullable=False) latitude = db.Column(db.Text, nullable=False) longitude = db.Column(db.Text, nullable=False) content = db.Column(db.Text, nullable=False) subscribed_users = db.relationship('Subscribe', backref=db.backref('post', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan', passive_deletes=True) def __repr__(self): return f"Travel('{self.date_posted}')" def to_json(self): json_travel = { 'city': self.city, 'country': self.country, 'content': self.content, 'title': self.title, 'userid': self.user_id, 'id': self.id, 'start_date': self.start_date, 'end_date': self.end_date, 'date_posted': self.date_posted, 'latitude': self.latitude, 'longitude': self.longitude, 'username': self.traveler.username, 'profile_pic': self.traveler.image_file } return json_travel def to_json_with_sub_check(self, checkusersub): sub = self.subscribed_users.filter_by( subscriber_id=checkusersub).first() if not sub: isSub = False else: isSub = True json_travel = { 'city': self.city, 'country': self.country, 'content': self.content, 'title': self.title, 'userid': self.user_id, 'id': self.id, 'isSub': isSub, 'start_date': self.start_date, 'end_date': self.end_date, 'date_posted': self.date_posted, 'latitude': self.latitude, 'longitude': self.longitude, 'username': self.traveler.username, 'profile_pic': self.traveler.image_file } return json_travel
class Building(db.Model, DictBase): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String, nullable=False) title_info = db.Column(db.String) address = db.Column(db.String, nullable=False) year_build_start = db.Column(db.Integer, nullable=False) year_build_end = db.Column(db.Integer, nullable=False) latitude = db.Column(db.Float, nullable=False) longitude = db.Column(db.Float, nullable=False) architects = db.relationship('Architect', secondary=building_architect, backref=db.backref('buildings', lazy='dynamic')) styles = db.relationship('Style', secondary=building_style, backref=db.backref('buildings', lazy='dynamic')) leading_img_path = db.Column(db.String, nullable=False) images = db.relationship('BuildingImage', backref=db.backref('building')) text = db.Column(db.Text, nullable=False) station_id = db.Column(db.Integer, db.ForeignKey('metro_station.id'), nullable=False) station = db.relationship('MetroStation', backref=db.backref('buildings', lazy='dynamic')) district_id = db.Column(db.Integer, db.ForeignKey('district.id'), nullable=False) district = db.relationship('District', backref=db.backref('buildings', lazy='dynamic')) text_facts = db.relationship('BuildingTextFact', backref=db.backref('building')) number_facts = db.relationship('BuildingNumberFact', backref=db.backref('building')) def __str__(self): return self.title def to_dict(self): result = dictonify(self.__dict__) result.update({ 'images': [ { 'id': image.id, 'name': image.name, 'path': image.path } for image in self.images ], 'architects': [ { 'id': architect.id, 'name': architect.surname } for architect in self.architects ], 'styles': [ { 'id': style.id, 'name': style.name, 'path': style.building_img_path, } for style in self.styles ], 'number_facts': [ { 'id': fact.id, 'number': fact.number, 'name': fact.name } for fact in self.number_facts ], 'text_facts': [ { 'id': fact.id, 'text': fact.text } for fact in self.text_facts ] }) return result
class Organisation(db.Model): """ Describes an Organisation """ __tablename__ = "organisations" # Columns id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(512), nullable=False, unique=True) slug = db.Column(db.String(255), nullable=False, unique=True) logo = db.Column(db.String) # URL of a logo description = db.Column(db.String) url = db.Column(db.String) type = db.Column(db.Integer, default=OrganisationType.FREE.value, nullable=False) subscription_tier = db.Column(db.Integer) managers = db.relationship( User, secondary=organisation_managers, backref=db.backref("organisations", lazy="joined"), ) campaign = db.relationship( Campaign, secondary=campaign_organisations, backref="organisation" ) def create(self): """ Creates and saves the current model to the DB """ db.session.add(self) db.session.commit() @classmethod def create_from_dto(cls, new_organisation_dto: NewOrganisationDTO): """ Creates a new organisation from a DTO """ new_org = cls() new_org.name = new_organisation_dto.name new_org.slug = new_organisation_dto.slug or slugify(new_organisation_dto.name) new_org.logo = new_organisation_dto.logo new_org.description = new_organisation_dto.description new_org.url = new_organisation_dto.url new_org.type = OrganisationType[new_organisation_dto.type].value new_org.subscription_tier = new_organisation_dto.subscription_tier for manager in new_organisation_dto.managers: user = User.get_by_username(manager) if user is None: raise NotFound(f"User {manager} Not Found") new_org.managers.append(user) new_org.create() return new_org def update(self, organisation_dto: OrganisationDTO): """ Updates Organisation from DTO """ for attr, value in organisation_dto.items(): if attr == "type" and value is not None: value = OrganisationType[organisation_dto.type].value if attr == "managers": continue try: is_field_nullable = self.__table__.columns[attr].nullable if is_field_nullable and value is not None: setattr(self, attr, value) elif value is not None: setattr(self, attr, value) except KeyError: continue if organisation_dto.managers: self.managers = [] # Need to handle this in the loop so we can take care of NotFound users for manager in organisation_dto.managers: new_manager = User.get_by_username(manager) if new_manager is None: raise NotFound(f"User {manager} Not Found") self.managers.append(new_manager) db.session.commit() def delete(self): """ Deletes the current model from the DB """ db.session.delete(self) db.session.commit() def can_be_deleted(self) -> bool: """ An Organisation can be deleted if it doesn't have any projects or teams """ return len(self.projects) == 0 and len(self.teams) == 0 @staticmethod def get(organisation_id: int): """ Gets specified organisation by id :param organisation_id: organisation ID in scope :return: Organisation if found otherwise None """ return Organisation.query.get(organisation_id) @staticmethod def get_organisation_by_name(organisation_name: str): """Get organisation by name :param organisation_name: name of organisation :return: Organisation if found else None """ return Organisation.query.filter_by(name=organisation_name).first() @staticmethod def get_organisation_name_by_id(organisation_id: int): """Get organisation name by id :param organisation_id: :return: Organisation name """ return Organisation.query.get(organisation_id).name @staticmethod def get_all_organisations(): """ Gets all organisations""" return Organisation.query.order_by(Organisation.name).all() @staticmethod def get_organisations_managed_by_user(user_id: int): """ Gets organisations a user can manage """ query_results = ( Organisation.query.join(organisation_managers) .filter( (organisation_managers.c.organisation_id == Organisation.id) & (organisation_managers.c.user_id == user_id) ) .order_by(Organisation.name) .all() ) return query_results def as_dto(self, omit_managers=False): """ Returns a dto for an organisation """ organisation_dto = OrganisationDTO() organisation_dto.organisation_id = self.id organisation_dto.name = self.name organisation_dto.slug = self.slug organisation_dto.logo = self.logo organisation_dto.description = self.description organisation_dto.url = self.url organisation_dto.managers = [] organisation_dto.type = OrganisationType(self.type).name organisation_dto.subscription_tier = self.subscription_tier if omit_managers: return organisation_dto for manager in self.managers: org_manager_dto = OrganisationManagerDTO() org_manager_dto.username = manager.username org_manager_dto.picture_url = manager.picture_url organisation_dto.managers.append(org_manager_dto) return organisation_dto
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(20), unique=True, nullable=False) first_name = db.Column(db.String(20)) last_name = db.Column(db.String(20)) gender = db.Column(db.String(20), nullable=False) birth_date = db.Column(db.Date()) email = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(60), nullable=False) image_file = db.Column(db.String(20), nullable=False, default='default.jpg') posts = db.relationship('Posts', foreign_keys=[Posts.user_id], backref=db.backref('user', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') followed = db.relationship('Follow', foreign_keys=[Follow.follower_id], backref=db.backref('follower', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') followers = db.relationship('Follow', foreign_keys=[Follow.followed_id], backref=db.backref('followed', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') subscriptions = db.relationship('Subscribed', foreign_keys=[Subscribed.user_id], backref=db.backref('user', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') notifications = db.relationship('Notification', foreign_keys=[Notification.user_id], backref=db.backref('user', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') def __repr__(self): return f"User('{self.username}', '{self.email}', '{self.image_file}')" def follow(self, user): if not self.is_following(user): f = Follow(follower=self, followed=user) db.session.add(f) db.session.commit() def unfollow(self, user): f = self.followed.filter_by(followed_id=user.id).first() if f: db.session.delete(f) db.session.commit() def is_following(self, user): if user.id is None: return False return self.followed.filter_by(followed_id=user.id).first() is not None def is_followed_by(self, user): if user.id is None: return False return self.followers.filter_by( follower_id=user.id).first() is not None def subscribe(self, post): if not self.is_subscribed(post): s = Subscribed(user_id=self.id, post_id=post.id) db.session.add(s) db.session.commit() def unsubscribe(self, post): s = self.subscriptions.filter_by(post_id=post.id).first() if s: db.session.delete(s) db.session.commit() def is_subscribed(self, post): if post.id is None: return False return self.subscriptions.filter_by( post_id=post.id).first() is not None
class Message(db.Model): __tablename__ = "Messages" id = Column(Integer, primary_key=True, autoincrement=True) subject = Column(String(128), unique=True, nullable=False) body = Column(Text, nullable=False) created_at = Column(Integer, default=lambda: int(time()), nullable=False) is_read = Column(Boolean, default=False) # CONSIDER: maybe I don't need this field and can delegate it to the mapper table owner = Column(Integer, ForeignKey("Users.id"), nullable=False, index=True) sender = db.relationship("User", back_populates="messages_sent") recipients = db.relationship( "User", secondary=recipients, primaryjoin=(recipients.c.m_id == id), # messages_received will be set on User model backref=db.backref("messages_received", lazy="dynamic"), ) @classmethod def filter_by(cls, params: Dict[str, Any] = None) -> List["Message"]: """Return messages based on prams, if params is None return all messages.""" query = cls.query if params is None: params = {} recipient = params.pop("recipient", None) query_params = [getattr(cls, k) == v for k, v in params.items() if hasattr(cls, k)] if recipient is not None: query = query.join(recipients, recipients.c.m_id == cls.id) query_params.append(recipients.c.r_id == recipient) return query.filter(*query_params).all() @classmethod def find_by_id(cls, m_id: str) -> Optional["Message"]: # TODO: figure out how to add that message is read by recipient return cls.query.get(m_id) @classmethod def create(cls, subject: str, body: str, owner: int) -> "Message": return cls(subject=subject, body=body, owner=owner, created_at=int(time()), is_read=False) def delete(self, user: User) -> bool: try: if user in self.recipients: self.recipients.remove(user) elif self.owner == user.id: db.session.delete(self) db.session.commit() return True except SQLAlchemyError: # TODO: send email to support team or devops db.session.rollback() raise DeleteError( { "message": ( "Deleting a message failed due to the internal error. " "Support team is notified." ) } ) # raise ValidationError( {"message": "Message can be deleted only by a recipient or by a sender"} ) def save(self): try: db.session.add(self) db.session.commit() except SQLAlchemyError: db.session.rollback() raise SaveError( { "message": ( "Sending a message failed due to internal error. " "Support team is notified." ) } )
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(20), unique=True, nullable=False) first_name = db.Column(db.String(20)) last_name = db.Column(db.String(20)) gender = db.Column(db.String(20), nullable=False) birth_date = db.Column(db.Date()) email = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(60), nullable=False) image_file = db.Column(db.String(20), nullable=False, default='default.jpg') travels = db.relationship('Travel', backref='traveler', lazy='dynamic', cascade='all, delete-orphan') followed = db.relationship('Follow', foreign_keys=[Follow.follower_id], backref=db.backref('follower', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') followers = db.relationship('Follow', foreign_keys=[Follow.followed_id], backref=db.backref('followed', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') subcribed_posts = db.relationship('Subscriptions', backref='subcribed_posts', lazy='dynamic', cascade='all, delete-orphan') notifications = db.relationship('Notifications', backref='notifications', lazy='dynamic', cascade='all, delete-orphan') def __repr__(self): return f"User('{self.username}', '{self.email}', '{self.image_file}')" def update(self, data): for attr in data: setattr(self, attr, data[attr]) db.session.commit() def follow(self, user): if not self.is_following(user): f = Follow(follower=self, followed=user) db.session.add(f) db.session.commit() def unfollow(self, user): f = self.followed.filter_by(followed_id=user.id).first() if f: db.session.delete(f) db.session.commit() def is_following(self, user): if user.id is None: return False return self.followed.filter_by(followed_id=user.id).first() is not None def is_followed_by(self, user): if user.id is None: return False return self.followers.filter_by( follower_id=user.id).first() is not None # def get_followers(self): # User.query.join(User.followers).filter_by(followed_id=self.id).all() def is_subscribed(self, post): if post.id is None: return False return self.subcribed_posts.filter_by( post_id=post.id).first() is not None def subscribe(self, post): if not self.is_subscribed(post): f = Subscriptions(user_id=self.id, post_id=post.id) db.session.add(f) db.session.commit() def unsubscribe(self, post): found_post = self.subcribed_posts.filter_by(post_id=post.id).first() if found_post: db.session.delete(found_post) db.session.commit() ''' def show_notification(self, notification): found_notification = self.notifications.filter_by( notification_id = notification.notification_id).first() if found_notification.showed: Notifications.update().where( notification_id == found_notification.notification_id).values(showed=True) ''' def delete_notification(self, notification): found_notification = self.notifications.filter_by( notification_id=notification.notification_id).first() if found_notification: db.session.delete(found_notification) db.session.commit()
class Posts(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.Text, nullable=False) date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) start_date = db.Column(db.DateTime, nullable=False) end_date = db.Column(db.DateTime, nullable=False) country = db.Column(db.Text, nullable=False) city = db.Column(db.Text, nullable=False) latitude = db.Column(db.Integer, nullable=False) longitude = db.Column(db.Integer, nullable=False) content = db.Column(db.Text, nullable=False) subscribers = db.relationship('Subscribe', foreign_keys=[Subscribe.post_id], backref=db.backref('post', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') def __repr__(self): return f"Posts('{self.date_posted}')"