class Color(Field): __tablename__ = 'color' id = Column(db.ForeignKey('field.id'), primary_key=True) color_code = Column(db.String(10)) __mapper_args__ = {"polymorphic_identity": "color"}
class Activity(SurrogatePK, Model): __tablename__ = 'activity' activity_name = Column(db.String(200)) is_reaction = Column(db.Boolean, nullable=False, default=False) activity_type_id = reference_col("activity_type", nullable=False) activity_type = relationship("ActivityType", backref="activities") classroom_id = reference_col("classroom", nullable=False) classroom = relationship("Classroom", backref="activities") code = Column(db.String(100), nullable=False, unique=True) reaction_to_id = reference_col("activity", nullable=True) reactions = relationship("Activity", backref=db.backref('reaction_to', remote_side='Activity.id')) created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) updated_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) def __init__(self, activity_type_id, classroom, code, **kwargs): db.Model.__init__(self, activity_type_id=activity_type_id, classroom=classroom, code=code, **kwargs) @property def submissions_count(self): return len(self.submissions)
class Number(Field): __tablename__ = 'number' id = Column(db.ForeignKey("field.id"), primary_key=True) value = Column(db.Numeric()) __mapper_args__ = {"polymorphic_identity": "number"}
class Field(SurrogatePK, Model): __tablename__ = 'field' # id is needed for primary join, it does work with SurrogatePK class id = db.Column(db.Integer, primary_key=True) label = Column(db.String(100)) type = Column(db.String(50)) space_id = reference_col('space', nullable=True) space = relationship('Space', back_populates='fields') author_id = reference_col('userprofile', nullable=False) author = relationship("UserProfile", backref="fields") # https://docs.sqlalchemy.org/en/latest/_modules/examples/adjacency_list/adjacency_list.html parent_id = reference_col('field', nullable=True) children = relationship( "Field", # cascade deletions cascade="all, delete-orphan", # many to one + adjacency list - remote_side # is required to reference the 'remote' # column in the join condition. backref=db.backref("parent", remote_side=id), # children will be represented as a dictionary # on the "id" attribute. # collection_class=attribute_mapped_collection("id"), ) # https://docs.sqlalchemy.org/en/latest/orm/inheritance.html#joined-table-inheritance # https://docs.sqlalchemy.org/en/13/_modules/examples/inheritance/joined.html __mapper_args__ = { "polymorphic_identity": "field", "polymorphic_on": type, }
class Text(Field): __tablename__ = 'text' id = Column(db.ForeignKey("field.id"), primary_key=True) value = Column(db.String(200)) __mapper_args__ = {"polymorphic_identity": "text"}
class Theme(SurrogatePK, Model): __tablename__ = 'theme' title = Column(db.String(100), unique=True, nullable=False) description = Column(db.Text, nullable=False) slug = Column(db.String(100), unique=True, nullable=False) created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) updated_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) author_id = reference_col('userprofile', nullable=False) author = relationship("UserProfile", backref="themes") # can be draft, published, deleted status = Column(db.String(15), nullable=False, default="draft") cover_image = Column(db.String(512)) url = Column(db.String(512)) type = Column(db.String(50), nullable=False, default="Web") config = Column(JSONB) def __init__(self, author, title, description, slug=None, **kwargs): db.Model.__init__(self, author=author, title=title, description=description, slug=slug or slugify(title), **kwargs) def update_status(self, status): """Update Status""" self.status = status
class Select(Field): __tablename__ = 'select' id = Column(db.ForeignKey("field.id"), primary_key=True) selected_value = Column(db.String) possible_values = Column(db.JSON) __mapper_args__ = {"polymorphic_identity": "select"}
class Audio(Field): __tablename__ = 'audio' id = Column(db.ForeignKey("field.id"), primary_key=True) file_id = reference_col('file', nullable=True) file = relationship("File", backref=db.backref("audio", uselist=False)) duration = Column(db.Integer) audio_format = Column(db.String(50)) __mapper_args__ = {"polymorphic_identity": "audio"}
class Position(Field): __tablename__ = 'position' id = db.Column(db.ForeignKey("field.id"), primary_key=True) x = Column(db.Numeric(), default=0) y = Column(db.Numeric(), default=0) z = Column(db.Numeric(), default=0) w = Column(db.Numeric(), default=1) __mapper_args__ = {"polymorphic_identity": "position"}
class Image(Field): __tablename__ = 'image' id = Column(db.ForeignKey("field.id"), primary_key=True) file_id = reference_col('file', nullable=True) file = relationship("File", backref=db.backref("image", uselist=False)) width = Column(db.Integer) height = Column(db.Integer) __mapper_args__ = {"polymorphic_identity": "image"}
class Object(Field): __tablename__ = 'object' id = Column(db.ForeignKey('field.id'), primary_key=True) folder = Column(db.String(512)) object_filename = Column(db.String(100)) thumbnail = Column(db.String(100)) attribute = Column(db.String(200)) __mapper_args__ = {"polymorphic_identity": "object"}
class ActivityType(SurrogatePK, Model): __tablename__ = 'activity_type' title = Column(db.String(100), nullable=False) slug = Column(db.String(100), nullable=False, unique=True) instructions = Column(db.Text, nullable=False) pdf_link = Column(db.String(512), nullable=False) def __init__(self, title, instructions, pdf_link, slug=None, **kwargs): db.Model.__init__(self, title=title, slug=slugify(title), instructions=instructions, pdf_link=pdf_link)
class Submission(SurrogatePK, Model): __tablename__ = 'submission' author = Column(db.String(200), nullable=False) approved = Column(db.Boolean(), default=False, nullable=False) file_type = Column(db.String(100), nullable=False) file_id = reference_col("file") file = relationship("File", backref=db.backref("submission", uselist=False)) activity_id = reference_col("activity", nullable=False) activity = relationship("Activity", backref="submissions") created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow)
class User(SurrogatePK, Model): __tablename__ = 'users' username = Column(db.String(80), unique=True, nullable=False) email = Column(db.String(100), unique=True, nullable=False) password = Column(db.Binary(128), nullable=True) created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) updated_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) bio = Column(db.String(300), nullable=True) image = Column(db.String(120), nullable=True) token: str = '' def __init__(self, username, email, password=None, **kwargs): """Create instance.""" db.Model.__init__(self, username=username, email=email, **kwargs) if password: self.set_password(password) else: self.password = None def set_password(self, password): """Set password.""" self.password = bcrypt.generate_password_hash(password) def check_password(self, value): """Check password.""" return bcrypt.check_password_hash(self.password, value) def __repr__(self): """Represent instance as a unique string.""" return '<User({username!r})>'.format(username=self.username)
class Link(Field): __tablename__ = 'link' id = Column(db.ForeignKey('field.id'), primary_key=True) linked_space_id = reference_col('space', nullable=False) linked_space = relationship( 'Space', backref=db.backref('link', uselist=False)) __mapper_args__ = {"polymorphic_identity": "link"}
class Classroom(SurrogatePK, Model): __tablename__ = 'classroom' classname = Column(db.String(200), nullable=False) slug = Column(db.String(200), nullable=False, unique=True) subject = Column(db.String(100)) age_students = Column(db.String(100)) school_id = reference_col("school", nullable=False) school = relationship("School", backref="classrooms") teacher_id = reference_col("userprofile", nullable=False) teacher = relationship("UserProfile", backref="classrooms") created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) def __init__(self, school, classname, teacher, slug=None, **kwargs): dtn = dt.datetime.now() date_slug = str(dtn.year % 100) + str(dtn.month) + \ str(dtn.day) + str(dtn.hour) + str(dtn.minute) db.Model.__init__(self, school=school, classname=classname, teacher=teacher, slug=slugify(classname + date_slug + str(teacher.id) + str(school.id)), **kwargs)
class File(Model): __tablename__ = 'file' id = Column(db.Integer, primary_key=True) filename = Column(db.String(50)) url = Column(db.String(512)) filemime = Column(db.String(255)) filesize = Column(db.Integer) filename_original = Column(db.String(200)) created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow)
class School(SurrogatePK, Model): __tablename__ = 'school' name = Column(db.String(200), nullable=False) country = Column(db.String(100), nullable=False) region = Column(db.String) type = Column(db.String(100), default="school") slug = Column(db.String(100), nullable=False, unique=True) created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) updated_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) def __init__(self, name, country, region, slug=None, **kwargs): db.Model.__init__(self, name=name, country=country, region=region, slug=slug or slugify(name + '-' + country + '-' + region), **kwargs)
class Project(SurrogatePK, Model): __tablename__ = 'project' title = Column(db.String(100), nullable=False) description = Column(db.Text, nullable=False) slug = Column(db.String(100), nullable=False, unique=True) created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) updated_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) author_id = reference_col('userprofile', nullable=False) author = relationship('UserProfile', backref=db.backref('projects')) # https://docs.sqlalchemy.org/en/latest/_modules/examples/inheritance/joined.html fields = relationship('Field', back_populates="project", cascade="all, delete-orphan") theme_id = reference_col("theme", nullable=False) theme = relationship("Theme", backref="projects") # can be draft, published, deleted status = Column(db.String(15), nullable=False, default="draft") favoriters = relationship('UserProfile', secondary=favoriter_assoc, backref='favorites', lazy='dynamic') tagList = relationship('Tags', secondary=tag_assoc, backref='projects') def __init__(self, author, title, description, slug=None, **kwargs): db.Model.__init__( self, author=author, title=title, description=description, slug=slug or slugify(title + "-" + str(uuid.uuid4().hex[:6].upper())), **kwargs) def favourite(self, profile): if not self.is_favourite(profile): self.favoriters.append(profile) return True return False def unfavourite(self, profile): if self.is_favourite(profile): self.favoriters.remove(profile) return True return False def is_favourite(self, profile): return bool( self.query.filter( favoriter_assoc.c.favoriter == profile.id).count()) def add_tag(self, tag): if tag not in self.tagList: self.tagList.append(tag) return True return False def remove_tag(self, tag): if tag in self.tagList: self.tagList.remove(tag) return True return False @property def favoritesCount(self): return len(self.favoriters.all()) @property def favorited(self): if current_user: profile = current_user.profile return self.query.join(Project.favoriters).filter( UserProfile.id == profile.id).count() == 1 return False