class DAN(db.Document): school = db.ReferenceField(School, reverse_delete_rule = CASCADE) users = db.ListField(db.ReferenceField(User, reverse_delete_rule = NULLIFY)) is_current = db.BooleanField(default=False) start = db.DateTimeField(default=datetime.datetime.now()) end = db.DateTimeField() def age(self): """ Age (in days). """ if self.end: diff = self.end - self.start return diff.days else: diff = datetime.datetime.now() - self.start return diff.days def clone(self, finalize=True): if finalize: self.end = datetime.datetime.now() self.is_current = False self.save() if '_id' in self.__dict__: del self.__dict__['_id'] if '_created' in self.__dict__: del self.__dict__['_created'] if '_changed_fields' in self.__dict__: del self.__dict__['_changed_fields'] self.id = ObjectId() self.start = datetime.datetime.now() self.end = None self.is_current = True
class Collection(BaseProposal): """ A collection object """ meta = {'collection': 'app_collection'} # directly included proposals proposals = db.ListField(db.ReferenceField(Proposal)) collections = db.ListField(db.ReferenceField('self')) # todo: url def __init__(self, *args, **kwargs): super(Collection, self).__init__(*args, **kwargs) if not self.id: self.interested.append(Interested(user=self.proposer)) self.num_interested = 1 def add_proposal(self, p): self.update(add_to_set__proposals=p) self.reload() def remove_proposal(self, p): self.update(pull__proposals=p) self.reload() def add_collection(self, c): self.update(add_to_set__collections=c) self.reload() def remove_collection(self, c): self.update(pull__collections=c) self.reload() def all_proposals(self): ''' Gets all events, including those from enclosed proposals and collections ''' all_proposals = {} for c in self.collections: all_proposals.update(c.all_proposals()) for p in self.proposals: all_proposals[p.id] = p return sorted(all_proposals.values(), key=operator.attrgetter('title')) def all_events(self, date_sorted=True): ''' Gets all events, including those from enclosed proposals and collections ''' all_events = {} for c in self.collections: all_events.update(c.all_events()) for p in self.proposals: for e in p.events: all_events[e.id] = e for e in self.events: all_events[e.id] = e if date_sorted: return sorted(all_events.values(), key=operator.attrgetter('start')) else: return all_events
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 Interested(db.EmbeddedDocument): """ Structure for holding information about someone being interested in a proposal """ date = db.DateTimeField(default=datetime.datetime.now()) user = db.ReferenceField(User) can_teach = db.BooleanField(default=False) can_organize = db.BooleanField(default=False) can_host = db.BooleanField(default=False)
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 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=256) 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)) available_weekday_morning = db.BooleanField(default=False) available_weekday_night = db.BooleanField(default=False) available_weekend_morning = db.BooleanField(default=False) available_weekend_night = db.BooleanField(default=False) # 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 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 OrganizeProposal(db.Document): start = db.DateTimeField(required=True) end = db.DateTimeField(required=True) title = db.StringField(max_length=1000, required=True) #short_description = db.StringField(max_length=255, required=True) description = db.StringField(max_length=1000000, required=True) teacher = db.StringField(max_length=1000, required=True) class_difficulty = db.StringField(max_length=1000) places = db.ListField(db.ReferenceField(Place), required=True)
class Stage(db.EmbeddedDocument): """ Structure for holding the stage of a proposal """ date = db.DateTimeField(default=datetime.datetime.now()) value = db.IntField(default=LIFE_ORIGIN) creator = db.ReferenceField(User) @property def pretty_date(self): return pretty_date(self.date)
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 Discussion(db.Document): """ Thread of comments. """ title = db.StringField(max_length=1000, 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) import datetime 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, # discussion = self, # ) # c.created = datetime.datetime.now() # 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()
class Event(db.Document, InterestedMixin): """ 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.""" start = db.DateTimeField(default=datetime.datetime.now(), required=True) end = db.DateTimeField(required=True) title = db.StringField(max_length=1000, required=True) creator = db.ReferenceField(User, reverse_delete_rule=NULLIFY) created = db.DateTimeField(default=datetime.datetime.now()) updated = db.DateTimeField(default=datetime.datetime.now()) #short_description = db.StringField(max_length=255, required=True) description = db.StringField(max_length=1000000, required=True) teacher = db.StringField(max_length=1000, required=True) class_difficulty = db.StringField(max_length=1000) places = db.ListField(db.ReferenceField(Place)) #schools = db.ListField(db.ReferenceField(School, reverse_delete_rule = NULLIFY)) def save(self, *args, **kwargs): """ Update the updated field before saving """ self.updated = datetime.datetime.now() super(Event, self).save(*args, **kwargs)
class Comment(db.Document): """ Each individual comment """ creator = db.ReferenceField(User, reverse_delete_rule = NULLIFY) import datetime 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(max_length=5000, required=True) is_deleted = db.BooleanField(default=False) def edit_comment(self, newText): self.text = newText self.save()
class Proposal(db.Document, InterestedMixin): """ 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)) title = db.StringField(max_length=1000, required=True) # A copy of the original description is kept description = db.StringField(max_length=1000000, required=True) #edited_description = db.StringField() # 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)) teachers = db.ListField(db.ReferenceField(User, reverse_delete_rule = NULLIFY)) 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 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