class BoothInfo(db.Model, CRUDMixin): __tablename__ = 'corner_booth_info' id = db.Column(db.Integer, primary_key=True, autoincrement=True) booth_id = db.Column(db.String(255)) # Basic Info booth_name = db.Column(db.String(255)) loc_text = db.Column(db.Text()) loc_lo = db.Column(db.String(255)) loc_la = db.Column(db.String(255)) city = db.Column(db.String(255)) district = db.Column(db.String(255)) business_district = db.Column(db.String(255)) phone_number = db.Column(db.String(255)) email = db.Column(db.String(255)) open_time = db.Column(db.String(255)) category = db.Column(db.String(255)) # About the owner booth_owner = db.Column(db.String(255)) booth_story = db.Column(db.Text()) # Miscs check_in_num = db.Column(db.Integer) priority = db.Column(db.Integer) create_time = db.Column(db.DateTime) update_time = db.Column(db.DateTime) create_by = db.Column(db.String(255)) disabled = db.Column(db.Boolean())
class Task(db.Model): id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False) user_id = db.Column(db.Integer, nullable=False) start_time = db.Column(db.DateTime(), nullable=True) end_time = db.Column(db.DateTime(), nullable=True) code = db.Column(db.Text(), nullable=False) shots = db.Column(db.Integer, nullable=False) schema = db.Column(db.Text(), nullable=True) status = db.Column(db.Enum(TaskStatusEnum), nullable=False) response = db.Column(db.JSON(), nullable=True) cost = db.Column(DECIMAL(precision=6, scale=2, unsigned=True), nullable=True)
class Json(db.Model): __tablename__ = 'json' json_id = db.Column(db.Integer, primary_key=True) json = db.Column(db.Text(500000), nullable=False) created_on = db.Column(db.DateTime, default=db.func.now()) url_id = db.Column(db.Integer, ForeignKey('url.url_id')) description = db.Column(db.String(300), default=None) active = db.Column(db.Boolean, default=0) user_id = db.Column(db.Integer, nullable=False) url = relationship("Url", back_populates="jsons") def __init__(self, json, url_id, description, user_id): self.json = json, self.url_id = url_id, self.description = description, self.user_id = user_id def __repr__(self): return "< models.Json Object ('url_id={} user_id={} json={} created_on={} description={} active={})>" \ .format(self.url_id, self.user_id, self.json, self.created_on, self.description, self.active) def as_dict(self): return { "json_id": self.json_id, "json": self.json, "created_on": str(self.created_on), "url_id": self.url_id, "description": self.description, "active": self.active, "user_id": self.user_id }
class Question(db.Model): ''' question ''' __tablename__ = 'question' id = db.Column(db.Integer, primary_key=True, autoincrement=True) title = db.Column(db.String(50), nullable=False) content = db.Column(db.Text(), nullable=False)
class Drugs(db.Model): """ Drug Model for storing drug related details """ __tablename__ = "Drugs" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) summary = db.Column(db.Text()) legal_status = db.Column(db.Text()) drug_testing = db.Column(db.Text()) way_consuming = db.Column(db.Text()) desired_effect = db.Column(db.Text()) secondary_effect = db.Column(db.Text()) risks_complications = db.Column(db.Text()) addiction = db.Column(db.Text()) risk_reduction_tips = db.Column(db.Text()) img = db.Column(db.Text()) type_id = db.Column(db.Integer, ForeignKey("Types.id"), nullable=False) takes = db.relationship('Takes', backref='drugs')
class BoothAccusation(db.Model, CRUDMixin): __tablename__ = 'corner_booth_accusation' id = db.Column(db.Integer, primary_key=True, autoincrement=True) booth_id = db.Column(db.String(255)) accusation = db.Column(db.Text()) reporter = db.Column(db.String(255)) report_time = db.Column(db.DateTime) status = db.Column(db.String(255))
class Comment(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(15), unique=True) email = db.Column(db.String(50)) comments = db.Column(db.Text()) def __init__(self, username, email, comments): self.username = username self.email = email self.comments = comments
class Notice(db.Model): __table_args__ = {'extend_existing': True} notice_id = db.Column(db.Integer, autoincrement=True, primary_key=True, nullable=False) org = db.Column(db.String(255), nullable=False) title = db.Column(db.String(255), nullable=False) time = db.Column(db.DateTime, nullable=False) content = db.Column(db.Text(255), nullable=False)
class User(DB.Model): __tablename__ = "users" __table_args__ = {'extend_existing': True} id = DB.Column(DB.Integer(), primary_key=True) nickname = DB.Column(DB.String(255), unique=True, nullable=False) password_hash = DB.Column(DB.String(512), nullable=False) email = DB.Column(DB.String(255), nullable=False) image_url = DB.Column(DB.String(255), nullable=False) footer_text = DB.Column(DB.Text()) about = DB.Column(DB.Text()) registration_date = DB.Column(DB.DateTime(), default=datetime.datetime.now(), onupdate=datetime.datetime.now(), nullable=False) def __repr__(self): return f"{self.nickname} with email: {self.email}" @staticmethod def try_login(nickname, password): user = User.query.filter_by( nickname=nickname).first() # nickname is uniq if check_password_hash(user.password_hash, password): login_user(user) return True else: return False # This is required for flask-login 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
class Cluster(db.Model): __tablename__ = 'cluster' id = db.Column(db.VARCHAR(32), default=generate_uuid, primary_key=True) org_id = db.Column(db.ForeignKey('organization.id', ondelete='CASCADE'), comment='组织id') user_id = db.Column(db.ForeignKey('user.id'), comment='添加cluster的用户id') name = db.Column(db.VARCHAR(64), comment='集群名称') host = db.Column(db.VARCHAR(64), comment='集群主机ip') port = db.Column(db.SmallInteger(), comment='集群端口(6443..)') token = db.Column(db.Text(), comment='远程连接授权的token') create_time = db.Column(db.BigInteger(), default=get_timestamp, comment='用户添加集群的时间')
class DocsInfo(db.Model): __tablename__ = "docs_info" d_id = db.Column(db.SmallInteger, primary_key=True, nullable=False, autoincrement=True) group_id = db.Column(db.SmallInteger, db.ForeignKey("doc_relation.d_id"), primary_key=True) title = db.Column(db.String(256), nullable=False) keys = db.Column(db.String(256)) url = db.Column(db.Text(), nullable=True) docs_type = db.Column(db.Enum('PDF', 'URL', 'HTML', 'DOC')) version = db.Column(db.String(6), nullable=False) author = db.Column(db.String(32), nullable=False) input_time = db.Column(db.DateTime(), nullable=False) update_time = db.Column(db.DateTime(), nullable=False) comment = db.Column(db.Text()) hits = db.Column(db.Integer()) details = db.Column(LONGTEXT) doc_md5 = db.Column(db.String(32))
class Blogpost(db.Model): id = db.Column(db.Integer, primary_key=True) parentId = db.Column(db.Integer, default=-1) title = db.Column(db.String(100)) text = db.Column(db.Text()) date = db.Column(db.DateTime()) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) replies = db.relationship('Blogpost', secondary=replies, primaryjoin='Blogpost.id==replies.c.original_id', secondaryjoin='Blogpost.id==replies.c.reply_id', backref=db.backref('posts', lazy='dynamic'), lazy='dynamic') def __init__(self, user_id, text, date, title=''): self.user_id = user_id self.title = title self.text = text self.date = date def set_parentId(self, pid): self.parentId = pid def __repr__(self): return '<Blogpost - {}>'.format(self.title) def serialize(self): if self.user_id != None: user = User.query.get(self.user_id) delta = datetime.datetime.now() - self.date diff = '' if delta.days > 0: diff = str(int(delta.days)) + ' day(s) ago' else: diff_time = delta.seconds if diff_time < 60: diff = str(int(delta.seconds)) + ' second(s) ago' elif diff_time < 3600: diff = str(int(delta.seconds / 60)) + ' minute(s) ago' else: diff = str(int(delta.seconds / 3600)) + ' second(s) ago' return { 'id': self.id, 'username': user.username, 'fname': user.first_name, 'title': self.title, 'text': self.text, 'date': diff, 'parentId': self.parentId }
class ForumComment(DB.Model): __tablename__ = "forum_comments" __table_args__ = {'extend_existing': True} id = DB.Column(DB.Integer(), primary_key=True) text = DB.Column(DB.Text(), nullable=False) likes = DB.Column(DB.Integer()) user_id = DB.Column(DB.Integer(), DB.ForeignKey("users.id")) forum_id = DB.Column(DB.Integer(), DB.ForeignKey("articles.id")) date = DB.Column(DB.DateTime(), default=datetime.datetime.now(), onupdate=datetime.datetime.now(), nullable=False) def __repr__(self): return f"ArticleComment with author_id: {self.user_id}, article_id: {self.article_id}, text: {self.text}"
class DocResponse(db.Model): __tablename__ = 'doc_response' d_id = db.Column(db.SmallInteger, primary_key=True, nullable=False, autoincrement=True) user = db.Column(db.String(32), nullable=False) time = db.Column(db.DateTime(), nullable=False) content = db.Column(db.Text(), nullable=False) resp_doc_id = db.Column(db.SmallInteger, db.ForeignKey("docs_info.d_id"), primary_key=True) rep_id = db.Column(db.Integer()) # 如果是针对某一条子记录的回复,则不为空
class Article(DB.Model): __tablename__ = "articles" __table_args__ = {'extend_existing': True} id = DB.Column(DB.Integer(), primary_key=True) title = DB.Column(DB.String(255), nullable=False) user_id = DB.Column(DB.Integer(), DB.ForeignKey("users.id")) author_name = DB.Column(DB.String(255), nullable=False) date = DB.Column(DB.DateTime(), default=datetime.datetime.now(), onupdate=datetime.datetime.now(), nullable=False) text = DB.Column(DB.Text(), nullable=False) likes = DB.Column(DB.Integer(), default=0) def __repr__(self): return f"Article \"{self.title}\" ..."
class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(20)) password = db.Column(db.String(20)) email = db.Column(db.String(40)) confirmed = db.Column(db.BOOLEAN, default=False) 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) posts = db.relationship('Post', backref='author', lazy='dynamic') def ping(self): self.last_seen = datetime.utcnow() db.session.add(self) @property def password(self): raise AttributeError('密码属性不可读') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password) def generate_confirmation_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'confirm': self.id}) def confirm(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return '激活失败' if data.get('confirm') != self.id: return '激活失败' self.confirmed = True db.session.add(self) return '激活成功'
class Advert(db.Model): __tablename__ = 'realty_advertisments' advert_id = db.Column(db.Integer, primary_key=True, index=True) settlement = db.Column(db.String(50)) under_construction = db.Column(db.Boolean) description = db.Column(db.Text(1500)) price = db.Column(db.Integer) oblast_district = db.Column(db.String(50), index=True) living_area = db.Column(db.Float, nullable=True) has_balcony = db.Column(db.Boolean) address = db.Column(db.String(50)) construction_year = db.Column(db.Integer, nullable=True) rooms_number = db.Column(db.Integer) premise_area = db.Column(db.Float) active = db.Column(db.Boolean, default=True) def __init__(self, **kwargs): db.Model.__init__(self, **kwargs) @classmethod def create(cls, **kwargs): instance = cls(**kwargs) return instance.save() def update(self, commit=True, **kwargs): for attr, value in kwargs.items(): setattr(self, attr, value) return commit and self.save() or self def save(self, commit=True): db.session.add(self) if commit: db.session.commit() return self @classmethod def get_by_id(cls, record_id): if ispositive_int(record_id): return cls.query.get(int(record_id)) return None def __repr__(self): return '<Ad {advert_id}>'.format(advert_id=self.advert_id)
class LearningDatapointSubmission(ModelBase): __tablename__ = 'learning_datapoint_submission' user_id = db.Column(db.Integer(), db.ForeignKey('registered_users.id', onupdate='CASCADE', ondelete='CASCADE'), primary_key=True) datapoint_id = db.Column(db.Integer(), db.ForeignKey('learning_datapoint.id', onupdate='CASCADE', ondelete='CASCADE'), primary_key=True) submission_data = db.Column(db.Text(), nullable=False) def __init__(self, user_id: int, datapoint_id: int, submission_data: Any): if not isinstance(user_id, int): raise expected('user_id', user_id, int) if not isinstance(datapoint_id, int): raise expected('datapoint_id', datapoint_id, int) if submission_data is None: raise ValueError('submission_data expected not None') self.user_id = user_id self.datapoint_id = datapoint_id self.submission_data = json.dumps(submission_data) @staticmethod def create( datapoint: LearningDatapoint, user: '******', submission_data: Any) -> 'Optional[LearningDatapointSubmission]': submission = LearningDatapointSubmission(user.id, datapoint.id, submission_data) db.session.add(submission) return submission def __hash__(self): return hash((self.user_id, self.datapoint_id))
class Blogpost(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100)) text = db.Column(db.Text()) date = db.Column(db.DateTime()) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) def __init__(self, user_id, text, date, title=''): self.user_id = user_id self.title = title self.text = text self.date = date def __repr__(self): return '<Blogpost - {}>'.format(self.title) def serialize(self): if self.user_id != None: user = User.query.get(self.user_id) delta = datetime.datetime.now() - self.date diff = '' if delta.days > 0: diff = str(int(delta.days)) + ' day(s) ago' else: diff_time = delta.seconds if diff_time < 60: diff = str(int(delta.seconds)) + ' second(s) ago' elif diff_time < 3600: diff = str(int(delta.seconds / 60)) + ' minute(s) ago' else: diff = str(int(delta.seconds / 3600)) + ' second(s) ago' return { 'id': self.id, 'username': user.username, 'fname': user.first_name, 'title': self.title, 'text': self.text, 'date': diff, }
class Message(CRUDMixin, db.Model): id = db.Column(db.Integer, primary_key=True) message = db.Column(db.Text()) from_who = db.Column(db.String(128)) to_who = db.Column(db.String(128)) is_delivered = db.Column(db.Boolean, default=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) def __init__(self, message, from_who, to_who): self.message = message self.from_who = from_who self.to_who = to_who def __repr__(self): return 'User {} send a message to {}'.format(self.from_who, self.to_who) def set_delivered(self, commit=True): self.is_delivered = True self.save(commit) def serialize(self): return {"message": self.message, "from": self.from_who} def is_from_user(self, username): return self.from_who == username def is_to_user(self, username): return self.to_who == username @classmethod def set_messages_delivered(cls, messages): for m in messages: m.set_delivered(commit=False) db.session.commit()
class AppUser(ModelBase): __tablename__ = 'app_user' id = db.Column(db.Integer(), primary_key=True, autoincrement=True) provider = db.Column(db.String(32), nullable=False) # String ID of the provider internal_id = db.Column(db.String(), nullable=False) # ID that is specific to the provider language = db.Column(db.String(5), nullable=False) # Flag indicating whether a user has been informed about the new site or not notified_new_site = db.Column(db.Boolean(), nullable=False, default=False, server_default=expression.false()) enabled = db.Column(db.Boolean(), nullable=False, default=True, server_default=expression.true()) data = db.Column(db.Text(), nullable=True) # Stores data specific to the provider __table_args__ = ( db.UniqueConstraint('provider', 'internal_id'), ) subscriptions = db.relationship('UserDayCampusPreference', backref='user', passive_deletes=True) feature_participations = db.relationship('FeatureParticipation', backref='user', passive_deletes=True) def __init__(self, provider: str, internal_id: str, language: str): if not isinstance(provider, str): raise expected('provider', provider, str) if not isinstance(internal_id, str): raise expected('internal_id', internal_id, str) if not isinstance(language, str): raise expected('language', language, str) self.provider = provider self.internal_id = internal_id self.language = language def set_campus(self, day: Day, campus: Campus, active=None): sub = UserDayCampusPreference.get_for_user(self, day) if sub is None: UserDayCampusPreference.create(self, day, campus, active=True if active is None else active) else: sub.campus = campus if active is not None: sub.active = active def set_day_active(self, day: Day, active: bool): sub = UserDayCampusPreference.get_for_user(self, day) if sub is None: if active: raise ValueError('Cannot set subscription active if there is no campus set') else: sub.active = active def get_campus(self, day: Day) -> 'Optional[Campus]': sub = UserDayCampusPreference.get_for_user(self, day) if sub is not None: return sub.campus else: return None def get_subscription(self, day: Day) -> 'Optional[UserDayCampusPreference]': return UserDayCampusPreference.get_for_user(self, day) def set_language(self, language: str): self.language = language def set_active(self, day: Day, active: bool): sub = UserDayCampusPreference.get_for_user(self, day) if sub is None: raise ValueError('User does not have a subscription on day {}'.format(day.name)) sub.active = active @staticmethod def create(provider: str, internal_id: str, language: str) -> 'AppUser': user = AppUser(provider, internal_id, language) db.session.add(user) return user def delete(self): db.session.delete(self) @staticmethod def find_subscribed_users_by_day(day: Day, provider=None) -> 'List[AppUser]': q = AppUser.query if provider: q = q.filter_by(provider=provider) return q.join(AppUser.subscriptions).filter(db.and_(UserDayCampusPreference.day == day, UserDayCampusPreference.active == expression.true(), AppUser.enabled == expression.true() )).order_by(AppUser.provider, AppUser.internal_id).all() @staticmethod def find_by_id(provider: str, internal_id: str) -> 'Optional[AppUser]': return AppUser.query.filter_by(provider=provider, internal_id=internal_id).first() @staticmethod def find_by_provider(provider: str) -> 'List[AppUser]': return AppUser.query.filter_by(provider=provider).order_by(AppUser.internal_id).all() def __hash__(self): return hash(self.id)
class LearningDatapoint(ModelBase): __tablename__ = 'learning_datapoint' id = db.Column(db.Integer(), primary_key=True, autoincrement=True) campus_id = db.Column(db.Integer(), db.ForeignKey('campus.id'), nullable=False) menu_day = db.Column(db.Date(), nullable=False) screenshot = db.Column(db.Text(), nullable=False) processed_data = db.Column(db.Text(), nullable=False) submissions = db.relationship('LearningDatapointSubmission', backref='datapoint', passive_deletes=True) def __init__(self, campus_id: int, menu_day: datetime.date, screenshot: str, processed_data: Any): if not isinstance(campus_id, int): raise expected('campus_id', campus_id, int) if not isinstance(menu_day, datetime.date): raise expected('menu_day', menu_day, datetime.date) if screenshot is None: raise ValueError('screenshot expected not None') if processed_data is None: raise ValueError('processed_data expected not None') self.campus_id = campus_id self.menu_day = menu_day self.screenshot = screenshot self.processed_data = json.dumps(processed_data) @staticmethod def create(campus: 'Campus', menu_day: datetime.date, screenshot: str, processed_data: Any) -> 'Optional[LearningDatapoint]': datapoint = LearningDatapoint(campus.id, menu_day, screenshot, processed_data) db.session.add(datapoint) return datapoint @staticmethod def find_by_id(datapoint_id: int) -> 'Optional[LearningDatapoint]': return LearningDatapoint.query.filter_by(id=datapoint_id).first() @staticmethod def get_all() -> 'List[LearningDatapoint]': return LearningDatapoint.query.all() @staticmethod def get_random(user: '******') -> 'Optional[LearningDatapoint]': return LearningDatapoint.query.order_by( expression.func.random()).filter( expression.not_( LearningDatapointSubmission.query.filter( LearningDatapoint.id == LearningDatapointSubmission.datapoint_id, LearningDatapointSubmission.user_id == user.id).exists())).first() def user_submit(self, user: '******', submission_data: Any): LearningDatapointSubmission.create(self, user, submission_data) def __hash__(self): return hash(self.id)
class Campus(ModelBase): __tablename__ = 'campus' id = db.Column(db.Integer(), primary_key=True, autoincrement=True) name = db.Column(db.String(128), nullable=False) short_name = db.Column(db.String(8), nullable=False) # TODO: Wouldn't it be easier to instead have a new table mapping keywords to campuses, resolving possible conflicts keywords = db.Column(db.Text(), default='', nullable=False) active = db.Column(db.Boolean(), default=True, nullable=False) external_id = db.Column(db.Integer(), nullable=False) menus = db.relationship('Menu', backref='campus', passive_deletes=True) closing_days = db.relationship('ClosingDays', backref='campus', passive_deletes=True) subscriptions = db.relationship('UserDayCampusPreference', backref='campus', passive_deletes=True) def __init__(self, name: str, short_name: str): if not isinstance(name, str): raise expected('name', name, str) if not isinstance(short_name, str): raise expected('short_name', short_name, str) self.name = name self.short_name = short_name.lower() self._set_keywords([short_name, ]) def get_keywords(self) -> List[str]: return self.keywords.split(_KEYWORDS_SEPARATOR) def add_keyword(self, keyword: str): if _KEYWORDS_SEPARATOR in keyword: raise ValueError('Cannot have a space (the separator) in a keyword: {}'.format(repr(keyword))) self._set_keywords(self.get_keywords() + [keyword.lower(), ]) def remove_keyword(self, keyword: str): self._set_keywords([kw for kw in self.get_keywords() if kw != keyword]) def _set_keywords(self, keywords: List[str]): separator = _KEYWORDS_SEPARATOR # XXX: Add separator at the front and end for queries self.keywords = separator + separator.join(set(kw for kw in keywords if kw)) + separator @staticmethod def create(name: str, short_name: str, keywords: List[str], external_id: int, add_to_db=True) -> 'Campus': result = Campus(name, short_name) result.external_id = external_id for keyword in keywords: result.add_keyword(keyword) if add_to_db: db.session.add(result) return result @staticmethod def get_by_id(campus_id: int) -> 'Optional[Campus]': return Campus.query.filter_by(id=campus_id).first() @staticmethod def get_by_external_id(external_id: int) -> 'Optional[Campus]': return Campus.query.filter_by(external_id=external_id).first() @staticmethod def get_by_short_name(short_name: str) -> 'Optional[Campus]': return Campus.query.filter_by(short_name=short_name).first() @staticmethod def find_by_keyword(keyword: str) -> 'List[Campus]': # XXX: Each keyword is prepended and appended with the separator return Campus.query.filter(Campus.keywords.contains(_KEYWORDS_SEPARATOR + keyword.lower() + _KEYWORDS_SEPARATOR, autoescape=True)).all() @staticmethod def get_all() -> 'List[Campus]': return Campus.query.order_by(Campus.id).all() @staticmethod def get_all_active() -> 'List[Campus]': return Campus.query.filter_by(active=True).order_by(Campus.id).all() def __hash__(self): return hash(self.id)
class MenuItem(ModelBase): __tablename__ = 'menu_item' id = db.Column(db.Integer(), primary_key=True, autoincrement=True) menu_id = db.Column(db.Integer(), db.ForeignKey('menu.id', onupdate='CASCADE', ondelete='CASCADE'), nullable=False) translatable_id = db.Column(db.Integer(), db.ForeignKey('translatable.id', onupdate='CASCADE', ondelete='RESTRICT'), nullable=False) external_id = db.Column(db.Integer(), unique=True, nullable=True, server_default=expression.null()) course_type = db.Column(db.Enum(CourseType), nullable=False) course_sub_type = db.Column(db.Enum(CourseSubType), nullable=False) course_attributes = db.Column(db.Text(), nullable=False, default='[]', server_default='[]') course_allergens = db.Column(db.Text(), nullable=False, default='[]', server_default='[]') price_students = db.Column(db.Numeric(4, 2), nullable=False) price_staff = db.Column(db.Numeric(4, 2), nullable=True) data_frozen = db.Column(db.Boolean(), nullable=False, server_default=expression.false()) def __init__(self, menu: Menu, translatable_id: int, course_type: CourseType, course_sub_type: CourseSubType, price_students: Decimal, price_staff: Optional[Decimal]): if not isinstance(menu, Menu): raise expected('menu', menu, Menu) if not isinstance(translatable_id, int): raise expected('translatable_id', translatable_id, int) if not isinstance(course_type, CourseType): raise expected('course_type', course_type, CourseType) if not isinstance(course_sub_type, CourseSubType): raise expected('course_sub_type', course_sub_type, CourseSubType) if not isinstance(price_students, Decimal): raise expected('price_students', price_students, Decimal) if price_staff is not None and not isinstance(price_staff, Decimal): raise expected_or_none('price_staff', price_staff, Decimal) self.menu = menu self.translatable_id = translatable_id self.course_type = course_type self.course_sub_type = course_sub_type self.price_students = price_students self.price_staff = price_staff def get_translation(self, language: str, translator: 'TranslationService') -> 'Translation': return self.translatable.get_translation(language, translator) @staticmethod def format_price(price: Decimal) -> str: if price == 0.0: return '' return locale.currency(price).replace(' ', '') def get_attributes(self) -> List[CourseAttributes]: # Stored as a list of strings or a list of ints (backwards compat) return [CourseAttributes(v) if isinstance(v, int) else CourseAttributes[v] for v in json.loads(self.course_attributes)] def set_attributes(self, attributes: List[CourseAttributes]): self.course_attributes = json.dumps([v.name for v in attributes]) def get_allergens(self) -> List[CourseAllergens]: # Stored as a list of strings return [CourseAllergens[v] for v in json.loads(self.course_allergens)] def set_allergens(self, allergens: List[CourseAllergens]): self.course_allergens = json.dumps([v.name for v in allergens]) def __hash__(self): return hash(self.id)
class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(64), unique=True, index=True) username = db.Column(db.String(64), unique=True, index=True) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) password_hash = db.Column(db.String(128)) confirmed = db.Column(db.Boolean, default=False) 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) avatar_hash = db.Column(db.String(32)) posts = db.relationship('Post', backref='author', lazy='dynamic') photos = db.relationship('Photo', backref='author', lazy='dynamic') albums = db.relationship('Album', backref='author', lazy='dynamic') 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') comments = db.relationship('Comment', backref='author', lazy='dynamic') def __init__(self, **kwargs): super(User, self).__init__(**kwargs) if self.role is None: if self.email == current_app.config['FLASKY_ADMIN']: self.role = Role.query.filter_by(permissions=0xff).first() if self.role is None: self.role = Role.query.filter_by(default=True).first() if self.email is not None and self.avatar_hash is None: self.avatar_hash = hashlib.md5( self.email.encode('utf-8')).hexdigest() @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password) def generate_confirmation_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'confirm': self.id}) def confirm(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('confirm') != self.id: return False self.confirmed = True db.session.add(self) db.session.commit() return True def generate_reset_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'reset': self.id}) def reset_password(self, token, new_password): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('reset') != self.id: return False self.password = new_password db.session.add(self) db.session.commit() return True def generate_change_email_token(self, new_email, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'change_email': self.id, 'new_email': new_email}) def change_email(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('change_email') != self.id: return False new_email = data.get('new_email') if new_email is None: return False if self.query.filter_by(email=new_email).first() is not None: return False self.email = new_email self.avatar_hash = hashlib.md5(self.email.encode('utf-8')).hexdigest() db.session.add(self) db.session.commit() return True def can(self, permissions): return self.role is not None and (self.role.permissions & permissions) == permissions def is_administrator(self): return self.can(Permission.ADMINISTER) def ping(self): self.last_seen = datetime.utcnow() db.session.add(self) db.session.commit() def gravatar(self, size=100, default='identicon', rating='g'): if request.is_secure: url = 'https://secure.gravatar.com/avatar' else: url = 'http://www.gravatar.com/avatar' hashtext = self.avatar_hash or hashlib.md5( self.email.encode('utf-8')).hexdigest() return '{url}/{hash}?s={size}&d={default}&r={rating}'.format( url=url, hash=hashtext, size=size, default=default, rating=rating) 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): return self.followed.filter_by(followed_id=user.id).first() is not None def is_followed_by(self, user): return self.followers.filter_by( follower_id=user.id).first() is not None @property def followed_posts(self): return Post.query.join(Follow, Follow.followed_id == Post.author_id)\ .filter(Follow.follower_id == self.id) @property def my_posts(self): return Post.query.filter_by(author_id=self.id) def generate_auth_token(self, expiration): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'id': self.id}) @staticmethod def verify_auth_token(token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return None return User.query.get(data['id']) def to_json(self): json_user = { 'url': url_for('api.get_post', id=self.id, _external=True), 'username': self.username, 'member_since': self.member_since, 'last_seen': self.last_seen, 'posts': url_for('api.get_user_posts', id=self.id, _external=True), 'followed_posts': url_for('api.get_user_followed_posts', id=self.id, _external=True), 'post_count': self.posts.count() } return json_user def __repr__(self): return '<User %r>' % self.username
class Item(db.Model): id = db.Column(db.Integer, primary_key=True) body = db.Column(db.Text(50)) done = db.Column(db.Boolean, default=False) author_id = db.Column(db.Integer, db.ForeignKey("user.id")) author = db.relationship("User", back_populates="items")
class Feature(ModelBase): __tablename__ = 'feature' id = db.Column(db.Integer(), primary_key=True, autoincrement=True) string_id = db.Column(db.String(256), nullable=False, unique=True) description = db.Column(db.Text()) globally_available = db.Column(db.Boolean(), default=False, nullable=False) participations = db.relationship('FeatureParticipation', backref='feature', passive_deletes=True) def __init__(self, string_id: str, description: str = None, globally_available=False): if not isinstance(string_id, str): raise expected('string_id', string_id, str) if description is not None and not isinstance(description, str): raise expected_or_none('description', description, str) if globally_available is not None and not isinstance(globally_available, bool): raise expected_or_none('globally_available', globally_available, bool) self.string_id = string_id self.description = description self.globally_available = globally_available @staticmethod def create(string_id: str, description: str = None, globally_available=False) -> 'Optional[Feature]': feature = Feature(string_id, description, globally_available) db.session.add(feature) return feature @staticmethod def find_by_id(string_id: str) -> 'Optional[Feature]': return Feature.query.filter_by(string_id=string_id).first() @staticmethod def get_all() -> 'List[Feature]': return Feature.query.all() @staticmethod def is_user_participating(user: Optional[AppUser], string_id: str) -> bool: feature = Feature.find_by_id(string_id) if feature is None: return False if feature.globally_available: return True if user is None: return False return FeatureParticipation.get_for_user(user, feature) is not None @staticmethod def set_user_participating(user: AppUser, string_id: str, participating: bool): feature = Feature.find_by_id(string_id) participation = FeatureParticipation.get_for_user(user, feature) if participating: if not participation: FeatureParticipation.create(user, feature) else: if participation: db.session.delete(feature) def __hash__(self): return hash(self.id)