old_contents: from datetime import datetime
  
  from mongoengine import *
  
  from core.datatypes import Element
  
  class LinkHistory(EmbeddedDocument):
  
      tag = StringField()
      description = StringField()
      first_seen = DateTimeField(default=datetime.now)
      last_seen = DateTimeField(default=datetime.now)
  
  class Link(Document):
  
      src = ReferenceField(Element, required=True, reverse_delete_rule=CASCADE)
      dst = ReferenceField(Element, required=True, reverse_delete_rule=CASCADE, unique_with='src')
      history = SortedListField(EmbeddedDocumentField(LinkHistory), ordering='last_seen', reverse=True)
  
      @staticmethod
      def connect(src, dst):
          try:
              l = Link(src=src, dst=dst).save()
          except NotUniqueError:
              l = Link.objects.get(src=src, dst=dst)
          return l
  
      def add_history(self, tag, description, first_seen=None, last_seen=None):
          # this is race-condition prone... think of a better way to do this
          if not first_seen:
              first_seen = datetime.utcnow()
          if not last_seen:
              last_seen = datetime.utcnow()
  
          if len(self.history) == 0:
              return self.modify(push__history=LinkHistory(tag=tag, description=description, first_seen=first_seen, last_seen=last_seen))
  
          last = self.history[0]
          if description == last.description:  # Description is unchanged, update timestamp
              return self.modify(set__history__0__last_seen=last_seen)
          else:  # Link description has changed, insert in link history
              return self.modify(push__history=LinkHistory(tag=tag, description=description, first_seen=first_seen, last_seen=last_seen))
  
new_contents: from datetime import datetime
  
  from mongoengine import *
  
  from core.datatypes import Element
  
  class LinkHistory(EmbeddedDocument):
  
      tag = StringField()
      description = StringField()
      first_seen = DateTimeField(default=datetime.now)
      last_seen = DateTimeField(default=datetime.now)
  
  class Link(Document):
  
      src = ReferenceField(Element, required=True, reverse_delete_rule=CASCADE)
      dst = ReferenceField(Element, required=True, reverse_delete_rule=CASCADE, unique_with='src')
      history = SortedListField(EmbeddedDocumentField(LinkHistory), ordering='last_seen', reverse=True)
  
      @staticmethod
      def connect(src, dst):
          try:
              l = Link(src=src, dst=dst).save()
          except NotUniqueError:
              l = Link.objects.get(src=src, dst=dst)
          return l
  
      def add_history(self, tag, description=None, first_seen=None, last_seen=None):
          # this is race-condition prone... think of a better way to do this
          if not first_seen:
              first_seen = datetime.utcnow()
          if not last_seen:
              last_seen = datetime.utcnow()
  
          if len(self.history) == 0:
              return self.modify(push__history=LinkHistory(tag=tag, description=description, first_seen=first_seen, last_seen=last_seen))
  
          last = self.history[0]
          if description == last.description:  # Description is unchanged, update timestamp
              return self.modify(set__history__0__last_seen=last_seen)
          else:  # Link description has changed, insert in link history
              return self.modify(push__history=LinkHistory(tag=tag, description=description, first_seen=first_seen, last_seen=last_seen))
  
subject: Make link description optional