class School(db.Document): name = db.StringField(max_length=64, required=True) title = db.StringField(max_length=255) about = db.StringField() styles = db.StringField() def __str__(self): return self.name
class User(db.Document, UserMixin): """ A user object that integrates with Flask-Login (via UserMixin and the authenticate method) """ email = db.EmailField(unique=True) username = db.StringField(unique=True, max_length=64) display_name = db.StringField(max_length=64) password = db.StringField(max_length=255) active = db.BooleanField(default=True) role = db.IntField(default=ROLE_USER) created = db.DateTimeField(default=datetime.datetime.now()) # School/s the user is following schools = db.ListField( db.ReferenceField(School, reverse_delete_rule=NULLIFY)) # following which schools? (list of schools) # committee memberships (list) def __init__(self, is_admin=False, *args, **kwargs): super(User, self).__init__(*args, **kwargs) password = kwargs.get('password', None) if not self.id and password is not None: self.set_password(password) if not self.id and self.display_name is None: self.display_name = self.username if not self.id and is_admin: self.role = ROLE_ADMIN def is_admin(self): return self.role == ROLE_ADMIN def set_password(self, password): self.password = generate_password_hash(password) def check_password(self, password): if self.password is None: return False return check_password_hash(self.password, password) @classmethod def authenticate(self, login, password): """ Used by my implementation of Flask-Login """ try: user = self.objects.get(Q(username=login) | Q(email=login)) if user: authenticated = user.check_password(password) else: authenticated = False return user, authenticated except: import traceback print(traceback.format_exc()) return None, False def __str__(self): return self.display_name
class Place(db.Document): """ A place where an event might happen """ name = db.StringField(max_length=255, required=True) address = db.StringField() geo = db.PointField() information = db.StringField() schools = db.ListField( db.ReferenceField(School, reverse_delete_rule=NULLIFY)) creator = db.ReferenceField(User, reverse_delete_rule=NULLIFY) created = db.DateTimeField(default=datetime.datetime.now()) def __str__(self): return self.name
class Proposal(BaseProposal): """ A proposal object """ meta = {'collection': 'proposal'} # Tags tags = db.ListField(db.StringField(max_length=30)) # School the proposal was made to schools = db.ListField( db.ReferenceField(School, reverse_delete_rule=NULLIFY)) # Context in which the proposal was made source = db.IntField(default=SOURCE_WEBSITE) # Which stage in the organizing process stage = db.ListField(db.EmbeddedDocumentField(Stage)) def __init__(self, *args, **kwargs): super(Proposal, self).__init__(*args, **kwargs) if not self.id: self.interested.append(Interested(user=self.proposer)) self.num_interested = 1 self.stage.append(Stage(creator=self.proposer, date=self.created)) @property def current_stage(self): current_stage = None for s in self.stage: if current_stage is None or s.date > current_stage.date: current_stage = s return current_stage
class BaseProposal(db.Document, InterestedMixin): meta = { 'allow_inheritance': True, 'abstract': True, } title = db.StringField(max_length=255) # A copy of the original description is kept description = db.StringField() edited_description = db.StringField() # School the proposal was made to schools = db.ListField( db.ReferenceField(School, reverse_delete_rule=NULLIFY)) # Person who made the proposal proposer = db.ReferenceField(User, reverse_delete_rule=NULLIFY) created = db.DateTimeField(default=datetime.datetime.now()) updated = db.DateTimeField(default=datetime.datetime.now()) published = db.BooleanField(default=True) # The proposal that this proposal "copies" copy_of = db.ReferenceField("self", reverse_delete_rule=NULLIFY) # Events events = db.ListField(db.ReferenceField(Event, reverse_delete_rule=NULLIFY)) # Discussions discussions = db.ListField( db.ReferenceField(Discussion, reverse_delete_rule=NULLIFY)) def add_event(self, event): self.update(add_to_set__events=event) self.reload() def remove_event(self, event): self.update(pull__events=event) self.reload() def add_discussion(self, discussion): self.update(add_to_set__discussions=discussion) self.reload() def remove_discussion(self, discussion): self.update(pull__discussions=discussion) self.reload() def __str__(self): return self.title
class Comment(db.Document): """ Each individual comment """ creator = db.ReferenceField(User, reverse_delete_rule=NULLIFY) created = db.DateTimeField(default=datetime.datetime.now()) updated = db.DateTimeField(default=datetime.datetime.now()) published = db.BooleanField(default=True) discussion = db.GenericReferenceField() # The actual content of the comment text = db.StringField()
class Event(db.Document): """ Every event has a single start and end time. This class does not handle repeating - it is very simple. Instead, it will provide a clone method and the logic of repeating or continuing events will be handled by the application.""" #Required fields start = db.DateTimeField(default=datetime.datetime.now(), required=True) end = db.DateTimeField() title = db.StringField(max_length=255) schools = db.ListField( db.ReferenceField(School, reverse_delete_rule=NULLIFY)) creator = db.ReferenceField(User, reverse_delete_rule=NULLIFY) created = db.DateTimeField(default=datetime.datetime.now()) updated = db.DateTimeField(default=datetime.datetime.now()) # Optional fields short_description = db.StringField(max_length=255) description = db.StringField() places = db.ListField(db.ReferenceField(Place)) def save(self, *args, **kwargs): """ Update the updated field before saving """ self.updated = datetime.datetime.now() super(Event, self).save(*args, **kwargs)
class Discussion(db.Document): """ Thread of comments. """ title = db.StringField(max_length=255, required=True) # The comments and pointers to certain important comments #comments = db.SortedListField(db.ReferenceField(Comment), ordering="created", reverse=True) num_comments = db.IntField(default=0) first_comment = db.ReferenceField(Comment) last_comment = db.ReferenceField(Comment) last_comment_time = db.DateTimeField(default=datetime.datetime.now()) # Setting priority might allow for control over the ordering of discussion threads priority = db.IntField(default=0) created = db.DateTimeField(default=datetime.datetime.now()) creator = db.ReferenceField(User, reverse_delete_rule=NULLIFY) published = db.BooleanField(default=True) schools = db.ListField( db.ReferenceField(School, reverse_delete_rule=NULLIFY)) def add_comment(self, text, user, time=None): """ Creates a new comment and adds it to discussion thread """ c = Comment( creator=user, text=text, created=time or datetime.datetime.now(), discussion=self, ) c.save() #self.update(add_to_set__comments=c) #self.reload() #self.update(set__num_comments=len(self.comments)) if not self.first_comment: self.first_comment = c self.last_comment = c self.last_comment_time = c.created self.save()