class Course(db.Document): """An AP course.""" name = db.StringField(max_length=80, unique=True) description = db.StringField(default='') requirements = db.StringField(default='') upload_required = db.BooleanField(default=False) open_for_applications = db.BooleanField(default=False)
class CourseApplication(db.EmbeddedDocument): """An application to a course.""" course = db.ReferenceField(Course) uploaded_content = db.ListField(db.FileField()) average_okay = db.BooleanField(default=False) have_met_reqs = db.BooleanField(default=False) # Status: pending, yes, maybe, no, nosampleprovided writing_sample_status = db.StringField(default='pending') # Status: pending, approved, rejected status = db.StringField(default='pending')
class Application(db.Document): """An application.""" submitter = db.ReferenceField(User) is_submitted = db.BooleanField(default=False) submit_date = db.DateTimeField() course_applications = db.EmbeddedDocumentListField(CourseApplication) taking_ap_courses = db.BooleanField(default=False) current_ap_courses = db.StringField(default='') test_scores = db.StringField(default='') teacher_recs = db.EmbeddedDocumentListField(TeacherRec) confirm_contacted_teachers = db.BooleanField(default=False)
class Spot(db.Document): name = db.StringField(required=True) user = db.ReferenceField(User) location = GeoPointField(required=True) wifi = db.IntField(min_value=0, max_value=5) power = db.BooleanField() category = db.StringField() comments = db.ListField(db.StringField()) creation_date = db.DateTimeField(default=datetime.datetime.utcnow) user_url = db.StringField() meta = { 'ordering': ['-creation_date'] } def __str__(self): return self.name def to_dict(self): data = self.to_mongo() data['creation_date'] = str(self.creation_date.timestamp()) data['id'] = str(self.id) del data['_id'] data['user'] = str(data['user']) return data def to_json(self): return json.dumps(self.to_dict())
class Queue(db.Document): """ Queue document serves as a global lock for upload jobs. """ in_progress = db.BooleanField() meta = {'collection': 'queue'}
class User(db.Document, UserMixin): """A user account object.""" name = db.StringField(max_length=255) email = db.EmailField(max_length=255, unique=True) password = db.StringField(max_length=255) phone_number = db.StringField(max_length=255) parent_name = db.StringField(max_length=255) parent_phone_number = db.StringField(max_length=255) parent_email = db.StringField(max_length=255) entering_grade = db.IntField() is_first_year_at_wshs = db.BooleanField(default=False) roles = db.SortedListField(db.ReferenceField(Role), default=[]) active = db.BooleanField(default=True)
class User(UserMixin, db.Document): email = db.EmailField(unique=True) password = db.StringField(required=True, min_length=32, max_length=120) creation_date = db.DateTimeField(default=datetime.datetime.utcnow) username = db.StringField(unique=True, required=True) about = db.StringField() slug = db.StringField(unique=True) locations = db.EmbeddedDocumentListField(UserLocation, default=[]) allow_community = db.BooleanField() current_location = GeoPointField() socials = db.DictField() image_path = db.ImageField(size=(600, 400), thumbnail=(200, 200)) def set_password(self, password): self.password = generate_password_hash(password) return self def check_password(self, password): return check_password_hash(self.password, password) @property def avatar(self): return '{}/{}'.format(app.config.get('AVATARS_URL'), self.id) @property def has_avatar(self): return bool(self.image_path) def clean_about(self): self.about = (Markup(self.about.replace('<br>', '\^n^')) .striptags().replace('\^n^', '\n')) def __str__(self): return str(self.username or 'Unknown') def to_dict(self): data = self.to_mongo() data['id'] = str(self.id) del data['_id'] del data['password'] return data def save(self, *args, **kwargs): if self.slug is None: try: User.objects.get(username=self.username) # If the code above is reach on the block try, it means that # there is a duplicate self.username = uniquify_username(self.username) except User.DoesNotExist: pass self.slug = slugify(self.username) return super().save(*args, **kwargs) meta = {'ordering': ['-creation_date']}
class CheckoutMeta(db.EmbeddedDocument): # constants DURATION_TYPE_UNKNOWN = 0 DURATION_TYPE_MINS = 1 DURATION_TYPE_HOURS = 2 DURATION_TYPE_DAYS = 3 # fields duration = db.FloatField(default=0) duration_type = db.IntField(default=DURATION_TYPE_UNKNOWN, choices=DURATION_TYPES) is_ooo = db.BooleanField(default=False) # out of office
class Spot(db.Document): name = db.StringField(required=True) user = db.ReferenceField(User) location = db.GeoPointField(required=True) wifi = db.IntField(min_value=0, max_value=5) power = db.BooleanField() category = db.StringField() comments = db.ListField(db.StringField()) creation_date = db.DateTimeField(default=datetime.datetime.utcnow) meta = {'ordering': ['-creation_date']} def __str__(self): return self.name
class User(db.Document): name = db.StringField(max_length=120, unique=True) email = db.StringField(max_length=150) # user id password = db.StringField(max_length=250) is_admin = db.BooleanField(default=False) meta = {'ordering': ['name']} # Flask-Login integration 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 __unicode__(self): return self.email
class Article(db.Document): title = db.StringField(required=True) content = db.StringField(required=True) creation_date = db.DateTimeField(default=datetime.datetime.utcnow) slug = db.StringField(required=True, default='no-title') author = db.ReferenceField(User, reverse_delete_rule='NULLIFY') language = db.StringField(min_length=2, max_length=2, default='en') images = db.ListField() publication_date = db.DateTimeField() published = db.BooleanField(default=False) def __str__(self): return str(self.title) def get_author(self): try: return self.author except DoesNotExist: return User.objects.get(slug='neomad') def extract_images(self): """ Extract images from the content, resize and save them locally if they are base64 encoded. Saves the list of images into the images list property. """ html = BeautifulSoup(self.content, 'html.parser') images = [] try: os.makedirs(self.get_images_path()) except FileExistsError: pass for img in html.find_all('img'): data = img.get('src') if is_base64(data): m = hashlib.md5() m.update(data.encode('utf-8')) img_name = m.hexdigest() img_path = '{}/{}'.format(self.get_images_path(), img_name) img_url = '{}/{}'.format(self.get_images_url(), img_name) save_base64_image(data, img_path, (1000, 800)) img['src'] = img_url images.append(img_url) else: images.append(data) for outdated_image in set(self.images) - set(images): os.remove( os.path.join(self.get_images_path(), os.path.basename(outdated_image))) self.images = images def get_images_path(self): return '{}/{}'.format(app.config['ARTICLE_IMG_PATH'], self.id) def get_images_url(self): return '{}/{}'.format(app.config['ARTICLE_IMG_URL'], self.id) @property def image(self): if len(self.images): return self.images[0] def delete(self, *args, **kwargs): parent = super(Article, self).delete(*args, **kwargs) path = self.get_images_path() shutil.rmtree(path) return parent def save(self, *args, **kwargs): self.slug = slugify(self.title) is_new = not self.id # when new, the id must exist before extracting images if is_new: super(Article, self).save(*args, **kwargs) self.extract_images() self.title = Markup(self.title).striptags() self.content = clean_html(self.content, ALLOWED_TAGS) self.language = detect(self.content) morph = self.morph() if self != morph: morph.pre_save(*args, **kwargs) return super(Article, self).save(*args, **kwargs) def morph(self): if (self.content and 'https://steemit.com/' in self.content): match = re.match('.*(https://steemit.com/[^<\s.]*)', self.content) url = match.groups()[0] return SteemitArticle(article=self, url=url) return self meta = { 'ordering': ['-publication_date'], 'indexes': ['-publication_date'] }
class Teacher(db.Document): """A teacher.""" name = db.StringField(unique=True) email = db.StringField(required=False) is_pseudo = db.BooleanField(default=False)